Actualización
This commit is contained in:
360
main/common_cartridge/export/Cc13Convert.php
Normal file
360
main/common_cartridge/export/Cc13Convert.php
Normal file
@@ -0,0 +1,360 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
class Cc13Convert
|
||||
{
|
||||
/**
|
||||
* Converts a course object into a CC13 package and writes it to disk.
|
||||
*
|
||||
* @param \Chamilo\CourseBundle\Component\CourseCopy\Course $objCourse The Course object is "augmented" with info from the api_get_course_info() function, into the "$objCourse->info" array attribute.
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function convert(string $packagedir, string $outdir, Chamilo\CourseBundle\Component\CourseCopy\Course $objCourse)
|
||||
{
|
||||
$dir = realpath($packagedir);
|
||||
if (empty($dir)) {
|
||||
throw new InvalidArgumentException('Directory does not exist!');
|
||||
}
|
||||
$odir = realpath($outdir);
|
||||
if (empty($odir)) {
|
||||
throw new InvalidArgumentException('Directory does not exist!');
|
||||
}
|
||||
|
||||
if (!empty($objCourse)) {
|
||||
//Initialize the manifest metadata class
|
||||
$meta = new CcMetadataManifest();
|
||||
|
||||
//Package metadata
|
||||
$metageneral = new CcMetadataGeneral();
|
||||
$metageneral->setLanguage($objCourse->info['language']);
|
||||
$metageneral->setTitle($objCourse->info['title'], $objCourse->info['language']);
|
||||
$metageneral->setDescription('', $objCourse->info['language']);
|
||||
$metageneral->setCatalog('category');
|
||||
$metageneral->setEntry($objCourse->info['categoryName']);
|
||||
$meta->addMetadataGeneral($metageneral);
|
||||
|
||||
// Create the manifest
|
||||
$manifest = new CcManifest();
|
||||
|
||||
$manifest->addMetadataManifest($meta);
|
||||
|
||||
$organization = null;
|
||||
|
||||
//Get the course structure - this will be transformed into organization
|
||||
//Step 1 - Get the list and order of sections/topics
|
||||
|
||||
$count = 1;
|
||||
$sections = [];
|
||||
$resources = $objCourse->resources;
|
||||
|
||||
// We check the quiz sections
|
||||
if (isset($resources['quiz'])) {
|
||||
$quizSections = self::getItemSections(
|
||||
$resources['quiz'], // array of quiz IDs generated by the course backup process
|
||||
'quiz',
|
||||
$count,
|
||||
$objCourse->info['code'],
|
||||
$resources[RESOURCE_QUIZQUESTION] // selected question IDs from the course export form
|
||||
);
|
||||
$sections = array_merge($sections, $quizSections);
|
||||
}
|
||||
|
||||
// We check the document sections
|
||||
if (isset($resources['document'])) {
|
||||
$documentSections = self::getItemSections(
|
||||
$resources['document'],
|
||||
'document',
|
||||
$count,
|
||||
$objCourse->info['code']
|
||||
);
|
||||
$sections = array_merge($sections, $documentSections);
|
||||
}
|
||||
|
||||
// We check the wiki sections
|
||||
if (isset($resources['wiki'])) {
|
||||
$wikiSections = self::getItemSections(
|
||||
$resources['wiki'],
|
||||
'wiki',
|
||||
$count,
|
||||
$objCourse->info['code']
|
||||
);
|
||||
$sections = array_merge($sections, $wikiSections);
|
||||
}
|
||||
|
||||
// We check the forum sections
|
||||
if (isset($resources['forum'])) {
|
||||
$forumSections = self::getItemSections(
|
||||
$resources['forum'],
|
||||
'forum',
|
||||
$count,
|
||||
$objCourse->info['code'],
|
||||
$resources['Forum_Category']
|
||||
);
|
||||
$sections = array_merge($sections, $forumSections);
|
||||
}
|
||||
|
||||
// We check the link sections
|
||||
if (isset($resources['link'])) {
|
||||
$linkSections = self::getItemSections(
|
||||
$resources['link'],
|
||||
'link',
|
||||
$count,
|
||||
$objCourse->info['code'],
|
||||
$resources['Link_Category']
|
||||
);
|
||||
$sections = array_merge($sections, $linkSections);
|
||||
}
|
||||
|
||||
//organization title
|
||||
$organization = new CcOrganization();
|
||||
foreach ($sections as $sectionid => $values) {
|
||||
$item = new CcItem();
|
||||
$item->title = $values[0];
|
||||
self::processSequence($item, $manifest, $values[1], $dir, $odir);
|
||||
$organization->addItem($item);
|
||||
}
|
||||
$manifest->putNodes();
|
||||
|
||||
if (!empty($organization)) {
|
||||
$manifest->addNewOrganization($organization);
|
||||
}
|
||||
|
||||
$manifestpath = $outdir.DIRECTORY_SEPARATOR.'imsmanifest.xml';
|
||||
$saved = $manifest->saveTo($manifestpath);
|
||||
|
||||
return $saved;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of type $sections[1]['quiz', [sequence]] where sequence is the result of a call to getSequence().
|
||||
*
|
||||
* @param string $courseCode The course code litteral
|
||||
* @param ?array $itmesExtraData If defined, represents the items IDs selected in the course export form
|
||||
*
|
||||
* @return array
|
||||
* @reference self::getSequence()
|
||||
*/
|
||||
protected static function getItemSections(array $itemData, string $itemType, int &$count, string $courseCode, ?array $itmesExtraData = null)
|
||||
{
|
||||
$sections = [];
|
||||
switch ($itemType) {
|
||||
case 'quiz':
|
||||
case 'document':
|
||||
case 'wiki':
|
||||
$convertType = $itemType;
|
||||
if ($itemType == 'wiki') {
|
||||
$convertType = 'Page';
|
||||
}
|
||||
$sectionid = $count;
|
||||
$sectiontitle = ucfirst($itemType);
|
||||
$sequence = self::getSequence($itemData, 0, $convertType, $courseCode, $itmesExtraData);
|
||||
$sections[$sectionid] = [$sectiontitle, $sequence];
|
||||
$count++;
|
||||
break;
|
||||
case 'link':
|
||||
$links = self::getSequence($itemData, null, $itemType);
|
||||
foreach ($links as $categoryId => $sequence) {
|
||||
$sectionid = $count;
|
||||
if (isset($itmesExtraData[$categoryId])) {
|
||||
$sectiontitle = $itmesExtraData[$categoryId]->title;
|
||||
} else {
|
||||
$sectiontitle = 'General';
|
||||
}
|
||||
$sections[$sectionid] = [$sectiontitle, $sequence];
|
||||
$count++;
|
||||
}
|
||||
break;
|
||||
case 'forum':
|
||||
if (isset($itmesExtraData)) {
|
||||
foreach ($itmesExtraData as $fcategory) {
|
||||
if (isset($fcategory->obj)) {
|
||||
$objCategory = $fcategory->obj;
|
||||
$sectionid = $count;
|
||||
$sectiontitle = $objCategory->cat_title;
|
||||
$sequence = self::getSequence($itemData, $objCategory->iid, $itemType);
|
||||
$sections[$sectionid] = [$sectiontitle, $sequence];
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $sections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of items by category and item ID ("test" level, not "question" level) with details like title,
|
||||
* comment (description), type, questions, max_attempt, etc.
|
||||
*
|
||||
* @param array $objItems Array of item objects as returned by the course backup code
|
||||
* @param ?int $categoryId
|
||||
* @param ?string $itemType
|
||||
* @param ?string $coursecode
|
||||
* @param ?array $itemQuestions
|
||||
*
|
||||
* @return array|mixed
|
||||
*/
|
||||
protected static function getSequence(array $objItems, ?int $categoryId = null, ?string $itemType = null, ?string $coursecode = null, ?array $itemQuestions = null)
|
||||
{
|
||||
$sequences = [];
|
||||
switch ($itemType) {
|
||||
case 'quiz':
|
||||
$sequence = [];
|
||||
foreach ($objItems as $objItem) {
|
||||
if ($categoryId === 0) {
|
||||
$questions = [];
|
||||
foreach ($objItem->obj->question_ids as $questionId) {
|
||||
if (isset($itemQuestions[$questionId])) {
|
||||
$questions[$questionId] = $itemQuestions[$questionId];
|
||||
}
|
||||
}
|
||||
// As weird as this may sound, the constructors for the different object types (found in
|
||||
// src/CourseBundle/Component/CourseCopy/Resources/[objecttype].php) store the object property
|
||||
// in the "obj" attribute. Old code...
|
||||
// So here we recover properties from the quiz object, including questions (array built above).
|
||||
$sequence[$categoryId][$objItem->obj->iid] = [
|
||||
'title' => $objItem->obj->title,
|
||||
'comment' => $objItem->obj->description,
|
||||
'cc_type' => 'quiz',
|
||||
'source_id' => $objItem->obj->iid,
|
||||
'questions' => $questions,
|
||||
'max_attempt' => $objItem->obj->max_attempt,
|
||||
'expired_time' => $objItem->obj->expired_time,
|
||||
'pass_percentage' => $objItem->obj->pass_percentage,
|
||||
'random_answers' => $objItem->obj->random_answers,
|
||||
'course_code' => $coursecode,
|
||||
];
|
||||
}
|
||||
}
|
||||
$sequences = $sequence[$categoryId];
|
||||
break;
|
||||
case 'document':
|
||||
$sequence = [];
|
||||
foreach ($objItems as $objItem) {
|
||||
if ($categoryId === 0) {
|
||||
$sequence[$categoryId][$objItem->source_id] = [
|
||||
'title' => $objItem->title,
|
||||
'comment' => $objItem->comment,
|
||||
'cc_type' => ($objItem->file_type == 'folder' ? 'folder' : 'resource'),
|
||||
'source_id' => $objItem->source_id,
|
||||
'path' => $objItem->path,
|
||||
'file_type' => $objItem->file_type,
|
||||
'course_code' => $coursecode,
|
||||
];
|
||||
}
|
||||
}
|
||||
$sequences = $sequence[$categoryId];
|
||||
break;
|
||||
case 'forum':
|
||||
foreach ($objItems as $objItem) {
|
||||
if ($categoryId == $objItem->obj->forum_category) {
|
||||
$sequence[$categoryId][$objItem->obj->forum_id] = [
|
||||
'title' => $objItem->obj->forum_title,
|
||||
'comment' => $objItem->obj->forum_comment,
|
||||
'cc_type' => 'forum',
|
||||
'source_id' => $objItem->obj->iid,
|
||||
];
|
||||
}
|
||||
}
|
||||
$sequences = $sequence[$categoryId];
|
||||
break;
|
||||
case 'page':
|
||||
foreach ($objItems as $objItem) {
|
||||
if ($categoryId === 0) {
|
||||
$sequence[$categoryId][$objItem->page_id] = [
|
||||
'title' => $objItem->title,
|
||||
'comment' => $objItem->content,
|
||||
'cc_type' => 'page',
|
||||
'source_id' => $objItem->page_id,
|
||||
'reflink' => $objItem->reflink,
|
||||
];
|
||||
}
|
||||
}
|
||||
$sequences = $sequence[$categoryId];
|
||||
break;
|
||||
case 'link':
|
||||
if (!isset($categoryId)) {
|
||||
$categories = [];
|
||||
foreach ($objItems as $objItem) {
|
||||
$categories[$objItem->category_id] = self::getSequence($objItems, $objItem->category_id, $itemType);
|
||||
}
|
||||
$sequences = $categories;
|
||||
} else {
|
||||
foreach ($objItems as $objItem) {
|
||||
if ($categoryId == $objItem->category_id) {
|
||||
$sequence[$categoryId][$objItem->source_id] = [
|
||||
'title' => $objItem->title,
|
||||
'comment' => $objItem->description,
|
||||
'cc_type' => 'url',
|
||||
'source_id' => $objItem->source_id,
|
||||
'url' => $objItem->url,
|
||||
'target' => $objItem->target,
|
||||
];
|
||||
}
|
||||
}
|
||||
$sequences = $sequence[$categoryId];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $sequences;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the different types of activities exported from the course.
|
||||
* When dealing with tests, the "sequence" provided here is a test, not a question.
|
||||
* For each sequence, call the corresponding CcConverter[Type] object instantiation method in export/src/converter/.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function processSequence(CcIItem &$item, CcIManifest &$manifest, array $sequence, string $packageroot, string $outdir)
|
||||
{
|
||||
if (!empty($sequence)) {
|
||||
foreach ($sequence as $seq) {
|
||||
$activity_type = ucfirst($seq['cc_type']);
|
||||
$activity_indentation = 0;
|
||||
$aitem = self::itemIndenter($item, $activity_indentation);
|
||||
$caller = "CcConverter{$activity_type}";
|
||||
if (class_exists($caller)) {
|
||||
$obj = new $caller($aitem, $manifest, $packageroot, $outdir);
|
||||
if (!$obj->convert($outdir, $seq)) {
|
||||
throw new RuntimeException("failed to convert {$activity_type}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static function itemIndenter(CcIItem &$item, $level = 0)
|
||||
{
|
||||
$indent = (int) $level;
|
||||
$indent = ($indent) <= 0 ? 0 : $indent;
|
||||
$nprev = null;
|
||||
$nfirst = null;
|
||||
for ($pos = 0, $size = $indent; $pos < $size; $pos++) {
|
||||
$nitem = new CcItem();
|
||||
$nitem->title = '';
|
||||
if (empty($nfirst)) {
|
||||
$nfirst = $nitem;
|
||||
}
|
||||
if (!empty($nprev)) {
|
||||
$nprev->addChildItem($nitem);
|
||||
}
|
||||
$nprev = $nitem;
|
||||
}
|
||||
$result = $item;
|
||||
if (!empty($nfirst)) {
|
||||
$item->addChildItem($nfirst);
|
||||
$result = $nprev;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
61
main/common_cartridge/export/Cc13ExportConvert.php
Normal file
61
main/common_cartridge/export/Cc13ExportConvert.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CourseBundle\Component\CourseCopy\CourseArchiver;
|
||||
|
||||
class Cc13ExportConvert
|
||||
{
|
||||
/**
|
||||
* Export the CommonCartridge object to the app/cache/course_backups/CourseCC13Archiver_[hash] directory.
|
||||
*
|
||||
* @param \Chamilo\CourseBundle\Component\CourseCopy\Course $objCourse
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public static function export($objCourse)
|
||||
{
|
||||
$permDirs = api_get_permissions_for_new_directories();
|
||||
$backupDirectory = CourseArchiver::getBackupDir();
|
||||
|
||||
// Create a temp directory
|
||||
$backupDir = $backupDirectory.'CourseCC13Archiver_'.api_get_unique_id();
|
||||
|
||||
if (mkdir($backupDir, $permDirs, true)) {
|
||||
$converted = Cc13Convert::convert($backupDirectory, $backupDir, $objCourse);
|
||||
if ($converted) {
|
||||
$imsccFileName = self::createImscc($backupDir, $objCourse);
|
||||
|
||||
return $imsccFileName;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $backupDir
|
||||
* @param $objCourse
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return string Filename of the created .imscc (zip) file
|
||||
*/
|
||||
public static function createImscc($backupDir, $objCourse)
|
||||
{
|
||||
$backupDirectory = CourseArchiver::getBackupDir();
|
||||
|
||||
$date = new \DateTime(api_get_local_time());
|
||||
|
||||
$imsccFileName = $objCourse->info['code'].'_'.$date->format('Ymd-His').'.imscc';
|
||||
$imsccFilePath = $backupDirectory.$imsccFileName;
|
||||
|
||||
// Zip the course-contents
|
||||
$zip = new \PclZip($imsccFilePath);
|
||||
$zip->create($backupDir, PCLZIP_OPT_REMOVE_PATH, $backupDir);
|
||||
|
||||
// Remove the temp-dir.
|
||||
rmdirr($backupDir);
|
||||
|
||||
return $imsccFileName;
|
||||
}
|
||||
}
|
||||
49
main/common_cartridge/export/src/CcForum.php
Normal file
49
main/common_cartridge/export/src/CcForum.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_forum.php under GNU/GPL license */
|
||||
|
||||
class CcForum extends CcGeneralFile
|
||||
{
|
||||
public const DEAFULTNAME = 'discussion.xml';
|
||||
protected $rootns = 'dt';
|
||||
protected $rootname = 'topic';
|
||||
protected $ccnamespaces = ['dt' => 'http://www.imsglobal.org/xsd/imsccv1p3/imsdt_v1p3',
|
||||
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance', ];
|
||||
protected $ccnsnames = ['dt' => 'http://www.imsglobal.org/profile/cc/ccv1p3/ccv1p3_imsdt_v1p3.xsd'];
|
||||
protected $title = null;
|
||||
protected $textType = 'text/plain';
|
||||
protected $text = null;
|
||||
protected $attachments = [];
|
||||
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = self::safexml($title);
|
||||
}
|
||||
|
||||
public function setText($text, $type = 'text/plain')
|
||||
{
|
||||
$this->text = self::safexml($text);
|
||||
$this->textType = $type;
|
||||
}
|
||||
|
||||
public function setAttachments(array $attachments)
|
||||
{
|
||||
$this->attachments = $attachments;
|
||||
}
|
||||
|
||||
protected function onSave()
|
||||
{
|
||||
$rns = $this->ccnamespaces[$this->rootns];
|
||||
$this->appendNewElementNs($this->root, $rns, 'title', $this->title);
|
||||
$text = $this->appendNewElementNs($this->root, $rns, 'text', $this->text);
|
||||
$this->appendNewAttributeNs($text, $rns, 'texttype', $this->textType);
|
||||
if (!empty($this->attachments)) {
|
||||
$attachments = $this->appendNewElementNs($this->root, $rns, 'attachments');
|
||||
foreach ($this->attachments as $value) {
|
||||
$att = $this->appendNewElementNs($attachments, $rns, 'attachment');
|
||||
$this->appendNewAttributeNs($att, $rns, 'href', $value);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
151
main/common_cartridge/export/src/CcItem.php
Normal file
151
main/common_cartridge/export/src/CcItem.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Item Class.
|
||||
*/
|
||||
class CcItem implements CcIItem
|
||||
{
|
||||
public $identifier = null;
|
||||
public $identifierref = null;
|
||||
public $isvisible = null;
|
||||
public $title = null;
|
||||
public $parameters = null;
|
||||
public $childitems = null;
|
||||
private $parentItem = null;
|
||||
private $isempty = true;
|
||||
|
||||
public function __construct($node = null, $doc = null)
|
||||
{
|
||||
if (is_object($node)) {
|
||||
$clname = get_class($node);
|
||||
if ($clname == 'CcResource') {
|
||||
$this->initNewItem();
|
||||
$this->identifierref = $node->identifier;
|
||||
$this->title = is_string($doc) && (!empty($doc)) ? $doc : 'item';
|
||||
} elseif ($clname == 'CcManifest') {
|
||||
$this->initNewItem();
|
||||
$this->identifierref = $node->manifestID();
|
||||
$this->title = is_string($doc) && (!empty($doc)) ? $doc : 'item';
|
||||
} elseif (is_object($doc)) {
|
||||
$this->processItem($node, $doc);
|
||||
} else {
|
||||
$this->initNewItem();
|
||||
}
|
||||
} else {
|
||||
$this->initNewItem();
|
||||
}
|
||||
}
|
||||
|
||||
public function attrValue(&$nod, $name, $ns = null)
|
||||
{
|
||||
return is_null($ns) ?
|
||||
($nod->hasAttribute($name) ? $nod->getAttribute($name) : null) :
|
||||
($nod->hasAttributeNS($ns, $name) ? $nod->getAttributeNS($ns, $name) : null);
|
||||
}
|
||||
|
||||
public function processItem(&$node, &$doc)
|
||||
{
|
||||
$this->identifier = $this->attrValue($node, "identifier");
|
||||
$this->structure = $this->attrValue($node, "structure");
|
||||
$this->identifierref = $this->attrValue($node, "identifierref");
|
||||
$atr = $this->attrValue($node, "isvisible");
|
||||
$this->isvisible = is_null($atr) ? true : $atr;
|
||||
$nlist = $node->getElementsByTagName('title');
|
||||
if (is_object($nlist) && ($nlist->length > 0)) {
|
||||
$this->title = $nlist->item(0)->nodeValue;
|
||||
}
|
||||
$nlist = $doc->nodeList("//imscc:item[@identifier='".$this->identifier."']/imscc:item");
|
||||
if ($nlist->length > 0) {
|
||||
$this->childitems = [];
|
||||
foreach ($nlist as $item) {
|
||||
$key = $this->attrValue($item, "identifier");
|
||||
$this->childitems[$key] = new CcItem($item, $doc);
|
||||
}
|
||||
}
|
||||
$this->isempty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one Child Item.
|
||||
*/
|
||||
public function addChildItem(CcIItem &$item)
|
||||
{
|
||||
if (is_null($this->childitems)) {
|
||||
$this->childitems = [];
|
||||
}
|
||||
$this->childitems[$item->identifier] = $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new child Item.
|
||||
*
|
||||
* @param string $title
|
||||
*
|
||||
* @return CcIItem
|
||||
*/
|
||||
public function add_new_child_item($title = '')
|
||||
{
|
||||
$sc = new CcItem();
|
||||
$sc->title = $title;
|
||||
$this->addChildItem($sc);
|
||||
|
||||
return $sc;
|
||||
}
|
||||
|
||||
public function attachResource($resource)
|
||||
{
|
||||
if ($this->hasChildItems()) {
|
||||
throw new Exception("Can not attach resource to item that contains other items!");
|
||||
}
|
||||
$resident = null;
|
||||
if (is_string($resource)) {
|
||||
$resident = $resource;
|
||||
} elseif (is_object($resource)) {
|
||||
$clname = get_class($resource);
|
||||
if ($clname == 'CcResource') {
|
||||
$resident = $resource->identifier;
|
||||
} elseif ($clname == 'CcManifest') {
|
||||
$resident = $resource->manifestID();
|
||||
} else {
|
||||
throw new Exception("Unable to attach resource. Invalid object.");
|
||||
}
|
||||
}
|
||||
if (is_null($resident) || (empty($resident))) {
|
||||
throw new Exception("Resource must have valid identifier!");
|
||||
}
|
||||
$this->identifierref = $resident;
|
||||
}
|
||||
|
||||
public function hasChildItems()
|
||||
{
|
||||
return is_array($this->childitems) && (count($this->childitems) > 0);
|
||||
}
|
||||
|
||||
public function child_item($identifier)
|
||||
{
|
||||
return $this->hasChildItems() ? $this->childitems[$identifier] : null;
|
||||
}
|
||||
|
||||
public function initClean()
|
||||
{
|
||||
$this->identifier = null;
|
||||
$this->isvisible = null;
|
||||
$this->title = null;
|
||||
$this->parameters = null;
|
||||
$this->childitems = null;
|
||||
$this->parentItem = null;
|
||||
$this->isempty = true;
|
||||
}
|
||||
|
||||
public function initNewItem()
|
||||
{
|
||||
$this->identifier = CcHelpers::uuidgen('I_');
|
||||
$this->isvisible = true; //default is true
|
||||
$this->title = null;
|
||||
$this->parameters = null;
|
||||
$this->childitems = null;
|
||||
$this->parentItem = null;
|
||||
$this->isempty = false;
|
||||
}
|
||||
}
|
||||
329
main/common_cartridge/export/src/CcManifest.php
Normal file
329
main/common_cartridge/export/src/CcManifest.php
Normal file
@@ -0,0 +1,329 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_manifest.php under GNU/GPL license */
|
||||
|
||||
class CcManifest extends XMLGenericDocument implements CcIManifest
|
||||
{
|
||||
private $ccversion = null;
|
||||
private $ccobj = null;
|
||||
private $rootmanifest = null;
|
||||
private $activemanifest = null;
|
||||
private $parentmanifest = null;
|
||||
private $parentparentmanifest = null;
|
||||
private $ares = [];
|
||||
private $mainidentifier = null;
|
||||
|
||||
public function __construct($ccver = 13, $activemanifest = null,
|
||||
$parentmanifest = null, $parentparentmanifest = null)
|
||||
{
|
||||
$this->ccversion = $ccver;
|
||||
$this->ccobj = new CcVersion13();
|
||||
parent::__construct('UTF-8', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Namespace for use XPATH.
|
||||
*/
|
||||
public function registerNamespacesForXpath()
|
||||
{
|
||||
$scnam = $this->activemanifest->getCcNamespaces();
|
||||
foreach ($scnam as $key => $value) {
|
||||
$this->registerNS($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Metadata For Manifest.
|
||||
*/
|
||||
public function addMetadataManifest(CcIMetadataManifest $met)
|
||||
{
|
||||
$metanode = $this->node("//imscc:manifest[@identifier='".
|
||||
$this->activemanifest->manifestID().
|
||||
"']/imscc:metadata");
|
||||
$nmeta = $this->activemanifest->createMetadataNode($met, $this->doc, $metanode);
|
||||
$metanode->appendChild($nmeta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Metadata For Resource.
|
||||
*
|
||||
* @param string $identifier
|
||||
*/
|
||||
public function addMetadataResource(CcIMetadataResource $met, $identifier)
|
||||
{
|
||||
$metanode = $this->node("//imscc:resource".
|
||||
"[@identifier='".
|
||||
$identifier.
|
||||
"']");
|
||||
$metanode2 = $this->node("//imscc:resource".
|
||||
"[@identifier='".
|
||||
$identifier.
|
||||
"']/imscc:file");
|
||||
$nspaces = $this->activemanifest->getCcNamespaces();
|
||||
$dnode = $this->appendNewElementNs($metanode2, $nspaces['imscc'], 'metadata');
|
||||
$this->activemanifest->createMetadataResourceNode($met, $this->doc, $dnode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Metadata For File.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param string $filename
|
||||
*/
|
||||
public function addMetadataFile(CcIMetadataFile $met, $identifier, $filename)
|
||||
{
|
||||
if (empty($met) || empty($identifier) || empty($filename)) {
|
||||
throw new Exception('Try to add a metadata file with nulls values given!');
|
||||
}
|
||||
|
||||
$metanode = $this->node("//imscc:resource".
|
||||
"[@identifier='".
|
||||
$identifier.
|
||||
"']/imscc:file".
|
||||
"[@href='".
|
||||
$filename.
|
||||
"']");
|
||||
|
||||
$nspaces = $this->activemanifest->getCcNamespaces();
|
||||
$dnode = $this->doc->createElementNS($nspaces['imscc'], "metadata");
|
||||
|
||||
$metanode->appendChild($dnode);
|
||||
|
||||
$this->activemanifest->createMetadataFileNode($met, $this->doc, $dnode);
|
||||
}
|
||||
|
||||
public function onCreate()
|
||||
{
|
||||
$this->activemanifest = new CcVersion13();
|
||||
$this->rootmanifest = $this->activemanifest;
|
||||
$result = $this->activemanifest->createManifest($this->doc);
|
||||
$this->registerNamespacesForXpath();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getRelativeBasePath()
|
||||
{
|
||||
return $this->activemanifest->base();
|
||||
}
|
||||
|
||||
public function parentManifest()
|
||||
{
|
||||
return new CcManifest($this, $this->parentmanifest, $this->parentparentmanifest);
|
||||
}
|
||||
|
||||
public function rootManifest()
|
||||
{
|
||||
return new CcManifest($this, $this->rootmanifest);
|
||||
}
|
||||
|
||||
public function manifestID()
|
||||
{
|
||||
return $this->activemanifest->manifestID();
|
||||
}
|
||||
|
||||
public function getManifestNamespaces()
|
||||
{
|
||||
return $this->rootmanifest->getCcNamespaces();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new organization.
|
||||
*/
|
||||
public function addNewOrganization(CcIOrganization &$org)
|
||||
{
|
||||
$norg = $this->activemanifest->createOrganizationNode($org, $this->doc);
|
||||
$orgnode = $this->node("//imscc:manifest[@identifier='".
|
||||
$this->activemanifest->manifestID().
|
||||
"']/imscc:organizations");
|
||||
$orgnode->appendChild($norg);
|
||||
}
|
||||
|
||||
public function getResources($searchspecific = '')
|
||||
{
|
||||
$reslist = $this->getResourceList($searchspecific);
|
||||
$resourcelist = [];
|
||||
foreach ($reslist as $resourceitem) {
|
||||
$resourcelist[] = new CcResources($this, $resourceitem);
|
||||
}
|
||||
|
||||
return $resourcelist;
|
||||
}
|
||||
|
||||
public function getCcNamespacePath($nsname)
|
||||
{
|
||||
if (is_string($nsname) && (!empty($nsname))) {
|
||||
$scnam = $this->activemanifest->getCcNamespaces();
|
||||
|
||||
return $scnam[$nsname];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getResourceList($searchspecific = '')
|
||||
{
|
||||
return $this->nodeList("//imscc:manifest[@identifier='".
|
||||
$this->activemanifest->manifestID().
|
||||
"']/imscc:resources/imscc:resource".$searchspecific);
|
||||
}
|
||||
|
||||
public function onLoad()
|
||||
{
|
||||
$this->registerNamespacesForXpath();
|
||||
$this->fillManifest();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onSave()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resource to the manifest.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function addResource(CcIResource $res, $identifier = null, $type = 'webcontent')
|
||||
{
|
||||
if (!$this->ccobj->valid($type)) {
|
||||
throw new Exception("Type invalid...");
|
||||
}
|
||||
|
||||
if ($res == null) {
|
||||
throw new Exception('Invalid Resource or dont give it');
|
||||
}
|
||||
$rst = $res;
|
||||
|
||||
// TODO: This has to be reviewed since it does not handle multiple files properly.
|
||||
// Dependencies.
|
||||
if (is_object($identifier)) {
|
||||
$this->activemanifest->createResourceNode($rst, $this->doc, $identifier);
|
||||
} else {
|
||||
$nresnode = null;
|
||||
|
||||
$rst->type = $type;
|
||||
if (!CcHelpers::isHtml($rst->filename)) {
|
||||
$rst->href = null;
|
||||
}
|
||||
|
||||
$this->activemanifest->createResourceNode($rst, $this->doc, $nresnode);
|
||||
foreach ($rst->files as $file) {
|
||||
$ident = $this->getIdentifierByFilename($file);
|
||||
if ($ident == null) {
|
||||
$newres = new CcResources($rst->manifestroot, $file);
|
||||
if (!CcHelpers::isHtml($file)) {
|
||||
$newres->href = null;
|
||||
}
|
||||
$newres->type = 'webcontent';
|
||||
$this->activemanifest->createResourceNode($newres, $this->doc, $nresnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tmparray = [$rst->identifier, $rst->files[0]];
|
||||
|
||||
return $tmparray;
|
||||
}
|
||||
|
||||
public function updateInstructoronly($identifier, $value = false)
|
||||
{
|
||||
if (isset($this->activemanifest->resources[$identifier])) {
|
||||
$resource = $this->activemanifest->resources[$identifier];
|
||||
$resource->instructoronly = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the resources nodes in the Manifest.
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
public function putNodes()
|
||||
{
|
||||
$resnodestr = "//imscc:manifest[@identifier='".$this->activemanifest->manifestID().
|
||||
"']/imscc:resources";
|
||||
$resnode = $this->node($resnodestr);
|
||||
|
||||
foreach ($this->activemanifest->resources as $k => $v) {
|
||||
($k);
|
||||
$depen = $this->checkIfExistInOther($v->files[0], $v->identifier);
|
||||
if (!empty($depen)) {
|
||||
$this->replaceFileXDependency($depen, $v->files[0]);
|
||||
$v->type = 'webcontent';
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->activemanifest->resources as $node) {
|
||||
$rnode = $this->activemanifest->createResourceNode($node, $this->doc, null);
|
||||
$resnode->appendChild($rnode);
|
||||
if ($node->instructoronly) {
|
||||
$metafileceduc = new CcMetadataResourceEducational();
|
||||
$metafileceduc->setValue(intended_user_role::INSTRUCTOR);
|
||||
$metafile = new CcMetadataResource();
|
||||
$metafile->addMetadataResourceEducational($metafileceduc);
|
||||
$this->activemanifest->createMetadataEducational($metafile, $this->doc, $rnode);
|
||||
}
|
||||
}
|
||||
|
||||
return $resnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO - implement this method - critical.
|
||||
*/
|
||||
private function fillManifest()
|
||||
{
|
||||
}
|
||||
|
||||
private function checkIfExistInOther($name, $identifier)
|
||||
{
|
||||
$status = [];
|
||||
foreach ($this->activemanifest->resources as $value) {
|
||||
if (($value->identifier != $identifier) && isset($value->files[$name])) {
|
||||
$status[] = $value->identifier;
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
private function replaceFileXDependency($depen, $name)
|
||||
{
|
||||
foreach ($depen as $key => $value) {
|
||||
($key);
|
||||
$ident = $this->getIdentifierByFilename($name);
|
||||
$this->activemanifest->resources[$value]->files =
|
||||
$this->arrayRemoveByValue($this->activemanifest->resources[$value]->files, $name);
|
||||
if (!in_array($ident, $this->activemanifest->resources[$value]->dependency)) {
|
||||
array_push($this->activemanifest->resources[$value]->dependency, $ident);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getIdentifierByFilename($name)
|
||||
{
|
||||
$result = null;
|
||||
if (isset($this->activemanifest->resourcesInd[$name])) {
|
||||
$result = $this->activemanifest->resourcesInd[$name];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function arrayRemoveByValue($arr, $value)
|
||||
{
|
||||
return array_values(array_diff($arr, [$value]));
|
||||
}
|
||||
|
||||
private function arrayRemoveByKey($arr, $key)
|
||||
{
|
||||
return array_values(array_diff_key($arr, [$key]));
|
||||
}
|
||||
}
|
||||
51
main/common_cartridge/export/src/CcMetadataGeneral.php
Normal file
51
main/common_cartridge/export/src/CcMetadataGeneral.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_manifest.php under GNU/GPL license */
|
||||
|
||||
/**
|
||||
* Metadata General Type.
|
||||
*/
|
||||
class CcMetadataGeneral
|
||||
{
|
||||
public $title = [];
|
||||
public $language = [];
|
||||
public $description = [];
|
||||
public $keyword = [];
|
||||
public $coverage = [];
|
||||
public $catalog = [];
|
||||
public $entry = [];
|
||||
|
||||
public function setCoverage($coverage, $language)
|
||||
{
|
||||
$this->coverage[] = [$language, $coverage];
|
||||
}
|
||||
|
||||
public function setDescription($description, $language)
|
||||
{
|
||||
$this->description[] = [$language, $description];
|
||||
}
|
||||
|
||||
public function setKeyword($keyword, $language)
|
||||
{
|
||||
$this->keyword[] = [$language, $keyword];
|
||||
}
|
||||
|
||||
public function setLanguage($language)
|
||||
{
|
||||
$this->language[] = [$language];
|
||||
}
|
||||
|
||||
public function setTitle($title, $language)
|
||||
{
|
||||
$this->title[] = [$language, $title];
|
||||
}
|
||||
|
||||
public function setCatalog($cat)
|
||||
{
|
||||
$this->catalog[] = [$cat];
|
||||
}
|
||||
|
||||
public function setEntry($entry)
|
||||
{
|
||||
$this->entry[] = [$entry];
|
||||
}
|
||||
}
|
||||
52
main/common_cartridge/export/src/CcMetadataManifest.php
Normal file
52
main/common_cartridge/export/src/CcMetadataManifest.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_manifest.php under GNU/GPL license */
|
||||
|
||||
class CcMetadataManifest implements CcIMetadataManifest
|
||||
{
|
||||
public $arraygeneral = [];
|
||||
public $arraytech = [];
|
||||
public $arrayrights = [];
|
||||
public $arraylifecycle = [];
|
||||
|
||||
public function addMetadataGeneral($obj)
|
||||
{
|
||||
if (empty($obj)) {
|
||||
throw new Exception('Medatada Object given is invalid or null!');
|
||||
}
|
||||
!is_null($obj->title) ? $this->arraygeneral['title'] = $obj->title : null;
|
||||
!is_null($obj->language) ? $this->arraygeneral['language'] = $obj->language : null;
|
||||
!is_null($obj->description) ? $this->arraygeneral['description'] = $obj->description : null;
|
||||
!is_null($obj->keyword) ? $this->arraygeneral['keyword'] = $obj->keyword : null;
|
||||
!is_null($obj->coverage) ? $this->arraygeneral['coverage'] = $obj->coverage : null;
|
||||
!is_null($obj->catalog) ? $this->arraygeneral['catalog'] = $obj->catalog : null;
|
||||
!is_null($obj->entry) ? $this->arraygeneral['entry'] = $obj->entry : null;
|
||||
}
|
||||
|
||||
public function addMetadataTechnical($obj)
|
||||
{
|
||||
if (empty($obj)) {
|
||||
throw new Exception('Medatada Object given is invalid or null!');
|
||||
}
|
||||
!is_null($obj->format) ? $this->arraytech['format'] = $obj->format : null;
|
||||
}
|
||||
|
||||
public function addMetadataRights($obj)
|
||||
{
|
||||
if (empty($obj)) {
|
||||
throw new Exception('Medatada Object given is invalid or null!');
|
||||
}
|
||||
!is_null($obj->copyright) ? $this->arrayrights['copyrightAndOtherRestrictions'] = $obj->copyright : null;
|
||||
!is_null($obj->description) ? $this->arrayrights['description'] = $obj->description : null;
|
||||
!is_null($obj->cost) ? $this->arrayrights['cost'] = $obj->cost : null;
|
||||
}
|
||||
|
||||
public function addMetadataLifecycle($obj)
|
||||
{
|
||||
if (empty($obj)) {
|
||||
throw new Exception('Medatada Object given is invalid or null!');
|
||||
}
|
||||
!is_null($obj->role) ? $this->arraylifecycle['role'] = $obj->role : null;
|
||||
!is_null($obj->entity) ? $this->arraylifecycle['entity'] = $obj->entity : null;
|
||||
!is_null($obj->date) ? $this->arraylifecycle['date'] = $obj->date : null;
|
||||
}
|
||||
}
|
||||
18
main/common_cartridge/export/src/CcMetadataResource.php
Normal file
18
main/common_cartridge/export/src/CcMetadataResource.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_metadata_resource.php under GNU/GPL license */
|
||||
|
||||
/**
|
||||
* Metadata Resource.
|
||||
*/
|
||||
class CcMetadataResource implements CcIMetadataResource
|
||||
{
|
||||
public $arrayeducational = [];
|
||||
|
||||
public function addMetadataResourceEducational($obj)
|
||||
{
|
||||
if (empty($obj)) {
|
||||
throw new Exception('Medatada Object given is invalid or null!');
|
||||
}
|
||||
$this->arrayeducational['value'] = (!is_null($obj->value) ? $obj->value : null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_metadata_resource.php under GNU/GPL license */
|
||||
|
||||
/**
|
||||
* Metadata Resource Educational Type.
|
||||
*/
|
||||
class CcMetadataResourceEducational
|
||||
{
|
||||
public $value = [];
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
$arr = [$value];
|
||||
$this->value[] = $arr;
|
||||
}
|
||||
}
|
||||
97
main/common_cartridge/export/src/CcOrganization.php
Normal file
97
main/common_cartridge/export/src/CcOrganization.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_organization.php under GNU/GPL license */
|
||||
|
||||
/**
|
||||
* Organization Class.
|
||||
*/
|
||||
class CcOrganization implements CcIOrganization
|
||||
{
|
||||
public $title = null;
|
||||
public $identifier = null;
|
||||
public $structure = null;
|
||||
public $itemlist = null;
|
||||
private $metadata = null;
|
||||
private $sequencing = null;
|
||||
|
||||
public function __construct($node = null, $doc = null)
|
||||
{
|
||||
if (is_object($node) && is_object($doc)) {
|
||||
$this->processOrganization($node, $doc);
|
||||
} else {
|
||||
$this->initNew();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one Item into the Organization.
|
||||
*/
|
||||
public function addItem(CcIItem &$item)
|
||||
{
|
||||
if (is_null($this->itemlist)) {
|
||||
$this->itemlist = [];
|
||||
}
|
||||
$this->itemlist[$item->identifier] = $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new Item into the Organization.
|
||||
*
|
||||
* @param string $title
|
||||
*
|
||||
* @return CcIItem
|
||||
*/
|
||||
public function addNewItem($title = '')
|
||||
{
|
||||
$nitem = new CcItem();
|
||||
$nitem->title = $title;
|
||||
$this->addItem($nitem);
|
||||
|
||||
return $nitem;
|
||||
}
|
||||
|
||||
public function hasItems()
|
||||
{
|
||||
return is_array($this->itemlist) && (count($this->itemlist) > 0);
|
||||
}
|
||||
|
||||
public function attrValue(&$nod, $name, $ns = null)
|
||||
{
|
||||
return is_null($ns) ?
|
||||
($nod->hasAttribute($name) ? $nod->getAttribute($name) : null) :
|
||||
($nod->hasAttributeNS($ns, $name) ? $nod->getAttributeNS($ns, $name) : null);
|
||||
}
|
||||
|
||||
public function processOrganization(&$node, &$doc)
|
||||
{
|
||||
$this->identifier = $this->attrValue($node, "identifier");
|
||||
$this->structure = $this->attrValue($node, "structure");
|
||||
$this->title = '';
|
||||
$nlist = $node->getElementsByTagName('title');
|
||||
if (is_object($nlist) && ($nlist->length > 0)) {
|
||||
$this->title = $nlist->item(0)->nodeValue;
|
||||
}
|
||||
$nlist = $doc->nodeList("//imscc:organization[@identifier='".$this->identifier."']/imscc:item");
|
||||
$this->itemlist = [];
|
||||
foreach ($nlist as $item) {
|
||||
$this->itemlist[$item->getAttribute("identifier")] = new CcItem($item, $doc);
|
||||
}
|
||||
$this->isempty = false;
|
||||
}
|
||||
|
||||
public function initNew()
|
||||
{
|
||||
$this->title = null;
|
||||
$this->identifier = CcHelpers::uuidgen('O_');
|
||||
$this->structure = 'rooted-hierarchy';
|
||||
$this->itemlist = null;
|
||||
$this->metadata = null;
|
||||
$this->sequencing = null;
|
||||
}
|
||||
|
||||
public function uuidgen()
|
||||
{
|
||||
$uuid = sprintf('%04x%04x', mt_rand(0, 65535), mt_rand(0, 65535));
|
||||
|
||||
return strtoupper(trim($uuid));
|
||||
}
|
||||
}
|
||||
98
main/common_cartridge/export/src/CcPage.php
Normal file
98
main/common_cartridge/export/src/CcPage.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_page.php under GNU/GPL license */
|
||||
|
||||
class CcPage extends CcGeneralFile
|
||||
{
|
||||
protected $rootns = 'xmlns';
|
||||
protected $rootname = 'html';
|
||||
protected $ccnamespaces = ['xmlns' => 'http://www.w3.org/1999/xhtml'];
|
||||
|
||||
protected $content = null;
|
||||
protected $title = null;
|
||||
protected $intro = null;
|
||||
|
||||
public function setContent($value)
|
||||
{
|
||||
// We are not cleaning up this one on purpose.
|
||||
$this->content = $value;
|
||||
}
|
||||
|
||||
public function setTitle($value)
|
||||
{
|
||||
$this->title = self::safexml($value);
|
||||
}
|
||||
|
||||
public function setIntro($value)
|
||||
{
|
||||
$this->intro = self::safexml(strip_tags($value));
|
||||
}
|
||||
|
||||
public function onSave()
|
||||
{
|
||||
$rns = $this->ccnamespaces[$this->rootns];
|
||||
// Add the basic tags.
|
||||
$head = $this->appendNewElementNs($this->root, $rns, 'head');
|
||||
$this->appendNewAttributeNs($head, $rns, 'profile', 'http://dublincore.org/documents/dc-html/');
|
||||
|
||||
// Linking Dublin Core Metadata 1.1.
|
||||
$link_dc = $this->appendNewElementNs($head, $rns, 'link');
|
||||
$this->appendNewAttributeNs($link_dc, $rns, 'rel', 'schema.DC');
|
||||
$this->appendNewAttributeNs($link_dc, $rns, 'href', 'http://purl.org/dc/elements/1.1/');
|
||||
$link_dcterms = $this->appendNewElementNs($head, $rns, 'link');
|
||||
$this->appendNewAttributeNs($link_dcterms, $rns, 'rel', 'schema.DCTERMS');
|
||||
$this->appendNewAttributeNs($link_dcterms, $rns, 'href', 'http://purl.org/dc/terms/');
|
||||
// Content type.
|
||||
$meta_type = $this->appendNewElementNs($head, $rns, 'meta');
|
||||
$this->appendNewAttributeNs($meta_type, $rns, 'name', 'DC.type');
|
||||
$this->appendNewAttributeNs($meta_type, $rns, 'scheme', 'DCTERMS.DCMIType');
|
||||
$this->appendNewAttributeNs($meta_type, $rns, 'content', 'Text');
|
||||
|
||||
// Content description.
|
||||
if (!empty($this->intro)) {
|
||||
$meta_description = $this->appendNewElementNs($head, $rns, 'meta');
|
||||
$this->appendNewAttributeNs($meta_description, $rns, 'name', 'DC.description');
|
||||
$this->appendNewAttributeNs($meta_description, $rns, 'content', $this->intro);
|
||||
}
|
||||
|
||||
$meta = $this->appendNewElementNs($head, $rns, 'meta');
|
||||
$this->appendNewAttributeNs($meta, $rns, 'http-equiv', 'Content-type');
|
||||
$this->appendNewAttributeNs($meta, $rns, 'content', 'text/html; charset=UTF-8');
|
||||
// Set the title.
|
||||
$title = $this->appendNewElementNs($head, $rns, 'title', $this->title);
|
||||
$body = $this->appendNewElementNs($this->root, $rns, 'body');
|
||||
// We are unable to use DOM for embedding HTML due to numerous content errors.
|
||||
// Therefore we place a dummy tag that will be later replaced with the real content.
|
||||
$this->appendNewElementNs($body, $rns, 'div', '##REPLACE##');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function saveTo($fname)
|
||||
{
|
||||
$result = $this->onSave();
|
||||
if ($result) {
|
||||
$dret = str_replace('<?xml version="1.0"?>'."\n", '', $this->viewXML());
|
||||
$dret = str_replace('<div>##REPLACE##</div>', $this->content, $dret);
|
||||
$result = (file_put_contents($fname, $dret) !== false);
|
||||
if ($result) {
|
||||
$this->filename = $fname;
|
||||
$this->processPath();
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function onCreate()
|
||||
{
|
||||
$impl = new DOMImplementation();
|
||||
$dtd = $impl->createDocumentType('html',
|
||||
'-//W3C//DTD XHTML 1.0 Strict//EN',
|
||||
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd');
|
||||
$doc = $impl->createDocument($this->ccnamespaces[$this->rootns], null, $dtd);
|
||||
$doc->formatOutput = true;
|
||||
$doc->preserveWhiteSpace = true;
|
||||
$this->doc = $doc;
|
||||
parent::onCreate();
|
||||
}
|
||||
}
|
||||
164
main/common_cartridge/export/src/CcResources.php
Normal file
164
main/common_cartridge/export/src/CcResources.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_resources.php under GNU/GPL license */
|
||||
|
||||
class CcResources implements CcIResource
|
||||
{
|
||||
public $identifier = null;
|
||||
public $type = null;
|
||||
public $dependency = [];
|
||||
public $identifierref = null;
|
||||
public $href = null;
|
||||
public $base = null;
|
||||
public $persiststate = null;
|
||||
public $metadata = [];
|
||||
public $filename = null;
|
||||
public $files = [];
|
||||
public $isempty = null;
|
||||
public $manifestroot = null;
|
||||
public $folder = null;
|
||||
public $instructoronly = false;
|
||||
|
||||
private $throwonerror = true;
|
||||
|
||||
public function __construct($manifest, $file, $folder = '', $throwonerror = true)
|
||||
{
|
||||
$this->throwonerror = $throwonerror;
|
||||
if (is_string($manifest)) {
|
||||
$this->folder = $folder;
|
||||
$this->processResource($manifest, $file, $folder);
|
||||
$this->manifestroot = $manifest;
|
||||
} elseif (is_object($manifest)) {
|
||||
$this->importResource($file, $manifest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add resource.
|
||||
*
|
||||
* @param string $fname
|
||||
* @param string $location
|
||||
*/
|
||||
public function addResource($fname, $location = '')
|
||||
{
|
||||
$this->processResource($fname, $location, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a resource.
|
||||
*/
|
||||
public function importResource(DOMElement &$node, CcIManifest &$doc)
|
||||
{
|
||||
$searchstr = "//imscc:manifest[@identifier='".$doc->manifestID().
|
||||
"']/imscc:resources/imscc:resource";
|
||||
$this->identifier = $this->getAttrValue($node, "identifier");
|
||||
$this->type = $this->getAttrValue($node, "type");
|
||||
$this->href = $this->getAttrValue($node, "href");
|
||||
$this->base = $this->getAttrValue($node, "base");
|
||||
$this->persiststate = null;
|
||||
$nodo = $doc->nodeList($searchstr."[@identifier='".
|
||||
$this->identifier."']/metadata/@href");
|
||||
$this->metadata = $nodo->nodeValue;
|
||||
$this->filename = $this->href;
|
||||
$nlist = $doc->nodeList($searchstr."[@identifier='".
|
||||
$this->identifier."']/imscc:file/@href");
|
||||
$this->files = [];
|
||||
foreach ($nlist as $file) {
|
||||
$this->files[] = $file->nodeValue;
|
||||
}
|
||||
$nlist = $doc->nodeList($searchstr."[@identifier='".
|
||||
$this->identifier."']/imscc:dependency/@identifierref");
|
||||
$this->dependency = [];
|
||||
foreach ($nlist as $dependency) {
|
||||
$this->dependency[] = $dependency->nodeValue;
|
||||
}
|
||||
$this->isempty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a attribute value.
|
||||
*
|
||||
* @param DOMElement $nod
|
||||
* @param string $name
|
||||
* @param string $ns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAttrValue(&$nod, $name, $ns = null)
|
||||
{
|
||||
if (is_null($ns)) {
|
||||
return $nod->hasAttribute($name) ? $nod->getAttribute($name) : null;
|
||||
}
|
||||
|
||||
return $nod->hasAttributeNS($ns, $name) ? $nod->getAttributeNS($ns, $name) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a resource.
|
||||
*
|
||||
* @param string $manifestroot
|
||||
* @param string $fname
|
||||
* @param string $folder
|
||||
*/
|
||||
public function processResource($manifestroot, &$fname, $folder)
|
||||
{
|
||||
$file = empty($folder) ? $manifestroot.'/'.$fname : $manifestroot.'/'.$folder.'/'.$fname;
|
||||
|
||||
if (!file_exists($file) && $this->throwonerror) {
|
||||
throw new Exception('The file doesnt exist!');
|
||||
}
|
||||
|
||||
getDepFiles($manifestroot, $fname, $this->folder, $this->files);
|
||||
array_unshift($this->files, $folder.$fname);
|
||||
$this->initEmptyNew();
|
||||
$this->href = $folder.$fname;
|
||||
$this->identifierref = $folder.$fname;
|
||||
$this->filename = $fname;
|
||||
$this->isempty = false;
|
||||
$this->folder = $folder;
|
||||
}
|
||||
|
||||
public function adjustPath($mroot, $fname)
|
||||
{
|
||||
$result = null;
|
||||
if (file_exists($fname->filename)) {
|
||||
$result = pathDiff($fname->filename, $mroot);
|
||||
} elseif (file_exists($mroot.$fname->filename) || file_exists($mroot.DIRECTORY_SEPARATOR.$fname->filename)) {
|
||||
$result = $fname->filename;
|
||||
toUrlPath($result);
|
||||
$result = trim($result, "/");
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function initClean()
|
||||
{
|
||||
$this->identifier = null;
|
||||
$this->type = null;
|
||||
$this->href = null;
|
||||
$this->base = null;
|
||||
$this->metadata = [];
|
||||
$this->dependency = [];
|
||||
$this->identifierref = null;
|
||||
$this->persiststate = null;
|
||||
$this->filename = '';
|
||||
$this->files = [];
|
||||
$this->isempty = true;
|
||||
}
|
||||
|
||||
public function initEmptyNew()
|
||||
{
|
||||
$this->identifier = CcHelpers::uuidgen('I_', '_R');
|
||||
$this->type = null;
|
||||
$this->href = null;
|
||||
$this->persiststate = null;
|
||||
$this->filename = null;
|
||||
$this->isempty = false;
|
||||
$this->identifierref = null;
|
||||
}
|
||||
|
||||
public function getManifestroot()
|
||||
{
|
||||
return $this->manifestroot;
|
||||
}
|
||||
}
|
||||
102
main/common_cartridge/export/src/CcVersion13.php
Normal file
102
main/common_cartridge/export/src/CcVersion13.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
class CcVersion13 extends CcVersion1
|
||||
{
|
||||
public const WEBCONTENT = 'webcontent';
|
||||
public const QUESTIONBANK = 'imsqti_xmlv1p3/imscc_xmlv1p3/question-bank';
|
||||
public const ASSESSMENT = 'imsqti_xmlv1p3/imscc_xmlv1p3/assessment';
|
||||
public const ASSOCIATEDCONTENT = 'associatedcontent/imscc_xmlv1p3/learning-application-resource';
|
||||
public const DISCUSSIONTOPIC = 'imsdt_xmlv1p3';
|
||||
public const WEBLINK = 'imswl_xmlv1p3';
|
||||
public const BASICLTI = 'imsbasiclti_xmlv1p3';
|
||||
|
||||
public static $checker = [self::WEBCONTENT,
|
||||
self::ASSESSMENT,
|
||||
self::ASSOCIATEDCONTENT,
|
||||
self::DISCUSSIONTOPIC,
|
||||
self::QUESTIONBANK,
|
||||
self::WEBLINK,
|
||||
self::BASICLTI, ];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ccnamespaces = ['imscc' => 'http://www.imsglobal.org/xsd/imsccv1p3/imscp_v1p1',
|
||||
'lomimscc' => 'http://ltsc.ieee.org/xsd/imsccv1p3/LOM/manifest',
|
||||
'lom' => 'http://ltsc.ieee.org/xsd/imsccv1p3/LOM/resource',
|
||||
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'cc' => 'http://www.imsglobal.org/xsd/imsccv1p3/imsccauth_v1p1',
|
||||
];
|
||||
|
||||
$this->ccnsnames = ['imscc' => 'http://www.imsglobal.org/profile/cc/ccv1p3/ccv1p3_imscp_v1p2_v1p0.xsd',
|
||||
'lomimscc' => 'http://www.imsglobal.org/profile/cc/ccv1p3/LOM/ccv1p3_lommanifest_v1p0.xsd',
|
||||
'lom' => 'http://www.imsglobal.org/profile/cc/ccv1p3/LOM/ccv1p3_lomresource_v1p0.xsd',
|
||||
];
|
||||
|
||||
$this->ccversion = '1.3.0';
|
||||
$this->camversion = '1.3.0';
|
||||
$this->_generator = 'Chamilo Common Cartridge generator';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if the type are valid or not.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid($type)
|
||||
{
|
||||
return in_array($type, self::$checker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Education Metadata (How To).
|
||||
*
|
||||
* @param object $met
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
public function createMetadataEducational($met, DOMDocument &$doc, $xmlnode)
|
||||
{
|
||||
$metadata = $doc->createElementNS($this->ccnamespaces['imscc'], 'metadata');
|
||||
$xmlnode->insertBefore($metadata, $xmlnode->firstChild);
|
||||
$lom = $doc->createElementNS($this->ccnamespaces['lom'], 'lom');
|
||||
$metadata->appendChild($lom);
|
||||
$educational = $doc->createElementNS($this->ccnamespaces['lom'], 'educational');
|
||||
$lom->appendChild($educational);
|
||||
|
||||
foreach ($met->arrayeducational as $value) {
|
||||
!is_array($value) ? $value = [$value] : null;
|
||||
foreach ($value as $v) {
|
||||
$userrole = $doc->createElementNS($this->ccnamespaces['lom'], 'intendedEndUserRole');
|
||||
$educational->appendChild($userrole);
|
||||
$nd4 = $doc->createElementNS($this->ccnamespaces['lom'], 'source', 'IMSGLC_CC_Rolesv1p2');
|
||||
$nd5 = $doc->createElementNS($this->ccnamespaces['lom'], 'value', $v[0]);
|
||||
$userrole->appendChild($nd4);
|
||||
$userrole->appendChild($nd5);
|
||||
}
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
protected function updateItems($items, DOMDocument &$doc, DOMElement &$xmlnode)
|
||||
{
|
||||
foreach ($items as $key => $item) {
|
||||
$itemnode = $doc->createElementNS($this->ccnamespaces['imscc'], 'item');
|
||||
$this->updateAttribute($doc, 'identifier', $key, $itemnode);
|
||||
$this->updateAttribute($doc, 'identifierref', $item->identifierref, $itemnode);
|
||||
if (!is_null($item->title)) {
|
||||
$titlenode = $doc->createElementNS($this->ccnamespaces['imscc'], 'title');
|
||||
$titlenode->appendChild(new DOMText($item->title));
|
||||
$itemnode->appendChild($titlenode);
|
||||
}
|
||||
if ($item->hasChildItems()) {
|
||||
$this->updateItems($item->childitems, $doc, $itemnode);
|
||||
}
|
||||
$xmlnode->appendChild($itemnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
main/common_cartridge/export/src/CcWebLink.php
Normal file
59
main/common_cartridge/export/src/CcWebLink.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_weblink.php under GNU/GPL license */
|
||||
|
||||
class CcWebLink extends CcGeneralFile
|
||||
{
|
||||
public const DEAFULTNAME = 'weblink.xml';
|
||||
|
||||
protected $rootns = 'wl';
|
||||
protected $rootname = 'webLink';
|
||||
protected $ccnamespaces = ['wl' => 'http://www.imsglobal.org/xsd/imsccv1p3/imswl_v1p3',
|
||||
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance', ];
|
||||
protected $ccnsnames = ['wl' => 'http://www.imsglobal.org/profile/cc/ccv1p3/ccv1p3_imswl_v1p3.xsd'];
|
||||
|
||||
protected $url = null;
|
||||
protected $title = null;
|
||||
protected $href = null;
|
||||
protected $target = '_self';
|
||||
protected $windowFeatures = null;
|
||||
|
||||
/**
|
||||
* Set the url title.
|
||||
*
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = self::safexml($title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the url specifics.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $target
|
||||
* @param string $windowFeatures
|
||||
*/
|
||||
public function setUrl($url, $target = '_self', $windowFeatures = null)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->target = $target;
|
||||
$this->windowFeatures = $windowFeatures;
|
||||
}
|
||||
|
||||
protected function onSave()
|
||||
{
|
||||
$rns = $this->ccnamespaces[$this->rootns];
|
||||
$this->appendNewElementNs($this->root, $rns, 'title', $this->title);
|
||||
$url = $this->appendNewElementNs($this->root, $rns, 'url');
|
||||
$this->appendNewAttributeNs($url, $rns, 'href', $this->url);
|
||||
if (!empty($this->target)) {
|
||||
$this->appendNewAttributeNs($url, $rns, 'target', $this->target);
|
||||
}
|
||||
if (!empty($this->windowFeatures)) {
|
||||
$this->appendNewAttributeNs($url, $rns, 'windowFeatures', $this->windowFeatures);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
86
main/common_cartridge/export/src/base/CcConverters.php
Normal file
86
main/common_cartridge/export/src/base/CcConverters.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_converters.php under GNU/GPL license */
|
||||
|
||||
abstract class CcConverters
|
||||
{
|
||||
protected $item = null;
|
||||
protected $manifest = null;
|
||||
protected $rootpath = null;
|
||||
protected $path = null;
|
||||
protected $defaultfile = null;
|
||||
protected $defaultname = null;
|
||||
protected $ccType = null;
|
||||
protected $doc = null;
|
||||
|
||||
/**
|
||||
* ctor.
|
||||
*
|
||||
* @param string $rootpath
|
||||
* @param string $path
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(CcIItem &$item, CcIManifest &$manifest, $rootpath, $path)
|
||||
{
|
||||
$rpath = realpath($rootpath);
|
||||
if (empty($rpath)) {
|
||||
throw new InvalidArgumentException('Invalid path!');
|
||||
}
|
||||
$rpath2 = realpath($path);
|
||||
if (empty($rpath)) {
|
||||
throw new InvalidArgumentException('Invalid path!');
|
||||
}
|
||||
$doc = new XMLGenericDocument();
|
||||
|
||||
$this->doc = $doc;
|
||||
$this->item = $item;
|
||||
$this->manifest = $manifest;
|
||||
$this->rootpath = $rpath;
|
||||
$this->path = $rpath2;
|
||||
}
|
||||
|
||||
/**
|
||||
* performs conversion.
|
||||
*
|
||||
* @param string $outdir - root directory of common cartridge
|
||||
* @param object $objCourse
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract public function convert($outdir, $objCourse);
|
||||
|
||||
/**
|
||||
* Is the element visible in the course?
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isVisible()
|
||||
{
|
||||
$tdoc = new XMLGenericDocument();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores any files that need to be stored.
|
||||
*/
|
||||
protected function store(CcGeneralFile $doc, $outdir, $title, $deps = null)
|
||||
{
|
||||
$rdir = new CcResourceLocation($outdir);
|
||||
$rtp = $rdir->fullpath(true).$this->defaultname;
|
||||
if ($doc->saveTo($rtp)) {
|
||||
$resource = new CcResources($rdir->rootdir(), $this->defaultname, $rdir->dirname(true));
|
||||
$resource->dependency = empty($deps) ? [] : $deps;
|
||||
$resource->instructoronly = !$this->isVisible();
|
||||
$res = $this->manifest->addResource($resource, null, $this->ccType);
|
||||
$resitem = new CcItem();
|
||||
$resitem->attachResource($res[0]);
|
||||
$resitem->title = $title;
|
||||
$this->item->addChildItem($resitem);
|
||||
} else {
|
||||
throw new RuntimeException("Unable to save file {$rtp}!");
|
||||
}
|
||||
}
|
||||
}
|
||||
53
main/common_cartridge/export/src/base/CcGeneralFile.php
Normal file
53
main/common_cartridge/export/src/base/CcGeneralFile.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_general.php under GNU/GPL license */
|
||||
|
||||
class CcGeneralFile extends XMLGenericDocument
|
||||
{
|
||||
/**
|
||||
* Root element.
|
||||
*
|
||||
* @var DOMElement
|
||||
*/
|
||||
protected $root = null;
|
||||
protected $rootns = null;
|
||||
protected $rootname = null;
|
||||
protected $ccnamespaces = [];
|
||||
protected $ccnsnames = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
foreach ($this->ccnamespaces as $key => $value) {
|
||||
$this->registerNS($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
protected function onCreate()
|
||||
{
|
||||
$rootel = $this->appendNewElementNs($this->doc,
|
||||
$this->ccnamespaces[$this->rootns],
|
||||
$this->rootname);
|
||||
//add all namespaces
|
||||
foreach ($this->ccnamespaces as $key => $value) {
|
||||
$dummy_attr = "{$key}:dummy";
|
||||
$this->doc->createAttributeNS($value, $dummy_attr);
|
||||
}
|
||||
|
||||
// add location of schemas
|
||||
$schemaLocation = '';
|
||||
foreach ($this->ccnsnames as $key => $value) {
|
||||
$vt = empty($schemaLocation) ? '' : ' ';
|
||||
$schemaLocation .= $vt.$this->ccnamespaces[$key].' '.$value;
|
||||
}
|
||||
|
||||
if (!empty($schemaLocation) && isset($this->ccnamespaces['xsi'])) {
|
||||
$this->appendNewAttributeNs($rootel,
|
||||
$this->ccnamespaces['xsi'],
|
||||
'xsi:schemaLocation',
|
||||
$schemaLocation);
|
||||
}
|
||||
|
||||
$this->root = $rootel;
|
||||
}
|
||||
}
|
||||
507
main/common_cartridge/export/src/base/CcVersion1.php
Normal file
507
main/common_cartridge/export/src/base/CcVersion1.php
Normal file
@@ -0,0 +1,507 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_version1.php under GNU/GPL license */
|
||||
|
||||
/**
|
||||
* Version 1 class of Common Cartridge.
|
||||
*/
|
||||
class CcVersion1 extends CcVersionBase
|
||||
{
|
||||
public const WEBCONTENT = 'webcontent';
|
||||
public const QUESTIONBANK = 'imsqti_xmlv1p2/imscc_xmlv1p0/question-bank';
|
||||
public const ASSESSMENT = 'imsqti_xmlv1p2/imscc_xmlv1p0/assessment';
|
||||
public const ASSOCIATEDCONTENT = 'associatedcontent/imscc_xmlv1p0/learning-application-resource';
|
||||
public const DISCUSSIONTOPIC = 'imsdt_xmlv1p0';
|
||||
public const WEBLINK = 'imswl_xmlv1p0';
|
||||
|
||||
public static $checker = [self::WEBCONTENT,
|
||||
self::ASSESSMENT,
|
||||
self::ASSOCIATEDCONTENT,
|
||||
self::DISCUSSIONTOPIC,
|
||||
self::QUESTIONBANK,
|
||||
self::WEBLINK, ];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ccnamespaces = ['imscc' => 'http://www.imsglobal.org/xsd/imscc/imscp_v1p1',
|
||||
'lomimscc' => 'http://ltsc.ieee.org/xsd/imscc/LOM',
|
||||
'lom' => 'http://ltsc.ieee.org/xsd/LOM',
|
||||
'voc' => 'http://ltsc.ieee.org/xsd/LOM/vocab',
|
||||
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
];
|
||||
|
||||
$this->ccnsnames = [
|
||||
'imscc' => 'http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/imscp_v1p2_localised.xsd',
|
||||
'lom' => 'http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_2/lomLoose_localised.xsd',
|
||||
'lomimscc' => 'http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_1/lomLoose_localised.xsd',
|
||||
'voc' => 'http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_2/vocab/loose.xsd',
|
||||
];
|
||||
|
||||
$this->ccversion = '1.0.0';
|
||||
$this->camversion = '1.0.0';
|
||||
$this->_generator = 'Common Cartridge generator';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if the type are valid or not.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid($type)
|
||||
{
|
||||
return in_array($type, self::$checker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Education Metadata (How To).
|
||||
*
|
||||
* @param object $met
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
public function createMetadataEducational($met, DOMDocument &$doc, $xmlnode)
|
||||
{
|
||||
$nd = $doc->createElementNS($this->ccnamespaces['lom'], 'educational');
|
||||
$nd2 = $doc->createElementNS($this->ccnamespaces['lom'], 'intendedEndUserRole');
|
||||
$nd3 = $doc->createElementNS($this->ccnamespaces['voc'], 'vocabulary');
|
||||
|
||||
$xmlnode->appendChild($nd);
|
||||
$nd->appendChild($nd2);
|
||||
$nd2->appendChild($nd3);
|
||||
|
||||
foreach ($met->arrayeducational as $name => $value) {
|
||||
!is_array($value) ? $value = [$value] : null;
|
||||
foreach ($value as $v) {
|
||||
$nd4 = $doc->createElementNS($this->ccnamespaces['voc'], $name, $v[0]);
|
||||
$nd3->appendChild($nd4);
|
||||
}
|
||||
}
|
||||
|
||||
return $nd;
|
||||
}
|
||||
|
||||
protected function onCreate(DOMDocument &$doc, $rootmanifestnode = null, $nmanifestID = null)
|
||||
{
|
||||
$doc->formatOutput = true;
|
||||
$doc->preserveWhiteSpace = true;
|
||||
|
||||
$this->manifestID = is_null($nmanifestID) ? CcHelpers::uuidgen('M_') : $nmanifestID;
|
||||
$mUUID = $doc->createAttribute('identifier');
|
||||
$mUUID->nodeValue = $this->manifestID;
|
||||
|
||||
if (is_null($rootmanifestnode)) {
|
||||
if (!empty($this->_generator)) {
|
||||
$comment = $doc->createComment($this->_generator);
|
||||
$doc->appendChild($comment);
|
||||
}
|
||||
|
||||
$rootel = $doc->createElementNS($this->ccnamespaces['imscc'], 'manifest');
|
||||
$rootel->appendChild($mUUID);
|
||||
$doc->appendChild($rootel);
|
||||
|
||||
// Add all namespaces.
|
||||
foreach ($this->ccnamespaces as $key => $value) {
|
||||
$dummy_attr = $key.":dummy";
|
||||
$doc->createAttributeNS($value, $dummy_attr);
|
||||
}
|
||||
|
||||
// Add location of schemas.
|
||||
$schemaLocation = '';
|
||||
foreach ($this->ccnsnames as $key => $value) {
|
||||
$vt = empty($schemaLocation) ? '' : ' ';
|
||||
$schemaLocation .= $vt.$this->ccnamespaces[$key].' '.$value;
|
||||
}
|
||||
$aSchemaLoc = $doc->createAttributeNS($this->ccnamespaces['xsi'], 'xsi:schemaLocation');
|
||||
$aSchemaLoc->nodeValue = $schemaLocation;
|
||||
$rootel->appendChild($aSchemaLoc);
|
||||
} else {
|
||||
$rootel = $doc->createElementNS($this->ccnamespaces['imscc'], 'imscc:manifest');
|
||||
$rootel->appendChild($mUUID);
|
||||
}
|
||||
|
||||
$metadata = $doc->createElementNS($this->ccnamespaces['imscc'], 'metadata');
|
||||
$schema = $doc->createElementNS($this->ccnamespaces['imscc'], 'schema', 'IMS Common Cartridge');
|
||||
$schemaversion = $doc->createElementNS($this->ccnamespaces['imscc'], 'schemaversion', $this->ccversion);
|
||||
|
||||
$metadata->appendChild($schema);
|
||||
$metadata->appendChild($schemaversion);
|
||||
$rootel->appendChild($metadata);
|
||||
|
||||
if (!is_null($rootmanifestnode)) {
|
||||
$rootmanifestnode->appendChild($rootel);
|
||||
}
|
||||
|
||||
$organizations = $doc->createElementNS($this->ccnamespaces['imscc'], 'organizations');
|
||||
$rootel->appendChild($organizations);
|
||||
$resources = $doc->createElementNS($this->ccnamespaces['imscc'], 'resources');
|
||||
$rootel->appendChild($resources);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function updateAttribute(DOMDocument &$doc, $attrname, $attrvalue, DOMElement &$node)
|
||||
{
|
||||
$busenew = (is_object($node) && $node->hasAttribute($attrname));
|
||||
$nResult = null;
|
||||
if (!$busenew && is_null($attrvalue)) {
|
||||
$node->removeAttribute($attrname);
|
||||
} else {
|
||||
$nResult = $busenew ? $node->getAttributeNode($attrname) : $doc->createAttribute($attrname);
|
||||
$nResult->nodeValue = $attrvalue;
|
||||
if (!$busenew) {
|
||||
$node->appendChild($nResult);
|
||||
}
|
||||
}
|
||||
|
||||
return $nResult;
|
||||
}
|
||||
|
||||
protected function updateAttributeNs(DOMDocument &$doc, $attrname, $attrnamespace, $attrvalue, DOMElement &$node)
|
||||
{
|
||||
$busenew = (is_object($node) && $node->hasAttributeNS($attrnamespace, $attrname));
|
||||
$nResult = null;
|
||||
if (!$busenew && is_null($attrvalue)) {
|
||||
$node->removeAttributeNS($attrnamespace, $attrname);
|
||||
} else {
|
||||
$nResult = $busenew ? $node->getAttributeNodeNS($attrnamespace, $attrname) :
|
||||
$doc->createAttributeNS($attrnamespace, $attrname);
|
||||
$nResult->nodeValue = $attrvalue;
|
||||
if (!$busenew) {
|
||||
$node->appendChild($nResult);
|
||||
}
|
||||
}
|
||||
|
||||
return $nResult;
|
||||
}
|
||||
|
||||
protected function getChildNode(DOMDocument &$doc, $itemname, DOMElement &$node)
|
||||
{
|
||||
$nlist = $node->getElementsByTagName($itemname);
|
||||
$item = is_object($nlist) && ($nlist->length > 0) ? $nlist->item(0) : null;
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
protected function updateChildItem(DOMDocument &$doc, $itemname, $itemvalue, DOMElement &$node, $attrtostore = null)
|
||||
{
|
||||
$tnode = $this->getChildNode($doc, 'title', $node);
|
||||
$usenew = is_null($tnode);
|
||||
$tnode = $usenew ? $doc->createElementNS($this->ccnamespaces['imscc'], $itemname) : $tnode;
|
||||
if (!is_null($attrtostore)) {
|
||||
foreach ($attrtostore as $key => $value) {
|
||||
$this->updateAttribute($doc, $key, $value, $tnode);
|
||||
}
|
||||
}
|
||||
$tnode->nodeValue = $itemvalue;
|
||||
if ($usenew) {
|
||||
$node->appendChild($tnode);
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateItems($items, DOMDocument &$doc, DOMElement &$xmlnode)
|
||||
{
|
||||
foreach ($items as $key => $item) {
|
||||
$itemnode = $doc->createElementNS($this->ccnamespaces['imscc'], 'item');
|
||||
$this->updateAttribute($doc, 'identifier', $key, $itemnode);
|
||||
$this->updateAttribute($doc, 'identifierref', $item->identifierref, $itemnode);
|
||||
$this->updateAttribute($doc, 'parameters', $item->parameters, $itemnode);
|
||||
if (!empty($item->title)) {
|
||||
$titlenode = $doc->createElementNS($this->ccnamespaces['imscc'],
|
||||
'title',
|
||||
$item->title);
|
||||
$itemnode->appendChild($titlenode);
|
||||
}
|
||||
if ($item->hasChildItems()) {
|
||||
$this->updateItems($item->childitems, $doc, $itemnode);
|
||||
}
|
||||
$xmlnode->appendChild($itemnode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Resource (How to).
|
||||
*
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
protected function createResource(CcIResource &$res, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
$usenew = is_object($xmlnode);
|
||||
$dnode = $usenew ? $xmlnode : $doc->createElementNS($this->ccnamespaces['imscc'], "resource");
|
||||
$this->updateAttribute($doc, 'identifier', $res->identifier, $dnode);
|
||||
$this->updateAttribute($doc, 'type', $res->type, $dnode);
|
||||
!is_null($res->href) ? $this->updateAttribute($doc, 'href', $res->href, $dnode) : null;
|
||||
$this->updateAttribute($doc, 'base', $res->base, $dnode);
|
||||
|
||||
foreach ($res->files as $file) {
|
||||
$nd = $doc->createElementNS($this->ccnamespaces['imscc'], 'file');
|
||||
$ndatt = $doc->createAttribute('href');
|
||||
$ndatt->nodeValue = $file;
|
||||
$nd->appendChild($ndatt);
|
||||
$dnode->appendChild($nd);
|
||||
}
|
||||
$this->resources[$res->identifier] = $res;
|
||||
$this->resourcesInd[$res->files[0]] = $res->identifier;
|
||||
|
||||
foreach ($res->dependency as $dependency) {
|
||||
$nd = $doc->createElementNS($this->ccnamespaces['imscc'], 'dependency');
|
||||
$ndatt = $doc->createAttribute('identifierref');
|
||||
$ndatt->nodeValue = $dependency;
|
||||
$nd->appendChild($ndatt);
|
||||
$dnode->appendChild($nd);
|
||||
}
|
||||
|
||||
return $dnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an Item Folder (How To).
|
||||
*
|
||||
* @param DOMElement $xmlnode
|
||||
*/
|
||||
protected function createItemFolder(CcIOrganization &$org, DOMDocument &$doc, DOMElement &$xmlnode = null)
|
||||
{
|
||||
$itemfoldernode = $doc->createElementNS($this->ccnamespaces['imscc'], 'item');
|
||||
$this->updateAttribute($doc, 'identifier', "root", $itemfoldernode);
|
||||
|
||||
if ($org->hasItems()) {
|
||||
$this->updateItems($org->itemlist, $doc, $itemfoldernode);
|
||||
}
|
||||
if (is_null($this->organizations)) {
|
||||
$this->organizations = [];
|
||||
}
|
||||
$this->organizations[$org->identifier] = $org;
|
||||
|
||||
$xmlnode->appendChild($itemfoldernode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an Organization (How To).
|
||||
*
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
protected function createOrganization(CcIOrganization &$org, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
$usenew = is_object($xmlnode);
|
||||
$dnode = $usenew ? $xmlnode : $doc->createElementNS($this->ccnamespaces['imscc'], "organization");
|
||||
$this->updateAttribute($doc, 'identifier', $org->identifier, $dnode);
|
||||
$this->updateAttribute($doc, 'structure', $org->structure, $dnode);
|
||||
|
||||
$this->createItemFolder($org, $doc, $dnode);
|
||||
|
||||
return $dnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Metadata For Manifest (How To).
|
||||
*
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
protected function createMetadataManifest(CcIMetadataManifest $met, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
$dnode = $doc->createElementNS($this->ccnamespaces['lomimscc'], "lom");
|
||||
if (!empty($xmlnode)) {
|
||||
$xmlnode->appendChild($dnode);
|
||||
}
|
||||
$dnodegeneral = empty($met->arraygeneral) ? null : $this->createMetadataGeneral($met, $doc, $xmlnode);
|
||||
$dnodetechnical = empty($met->arraytech) ? null : $this->createMetadataTechnical($met, $doc, $xmlnode);
|
||||
$dnoderights = empty($met->arrayrights) ? null : $this->createMetadataRights($met, $doc, $xmlnode);
|
||||
$dnodelifecycle = empty($met->arraylifecycle) ? null : $this->createMetadataLifecycle($met, $doc, $xmlnode);
|
||||
|
||||
!is_null($dnodegeneral) ? $dnode->appendChild($dnodegeneral) : null;
|
||||
!is_null($dnodetechnical) ? $dnode->appendChild($dnodetechnical) : null;
|
||||
!is_null($dnoderights) ? $dnode->appendChild($dnoderights) : null;
|
||||
!is_null($dnodelifecycle) ? $dnode->appendChild($dnodelifecycle) : null;
|
||||
|
||||
return $dnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Metadata For Resource (How To).
|
||||
*
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
protected function createMetadataResource(CcIMetadataResource $met, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
$dnode = $doc->createElementNS($this->ccnamespaces['lom'], "lom");
|
||||
|
||||
!empty($xmlnode) ? $xmlnode->appendChild($dnode) : null;
|
||||
!empty($met->arrayeducational) ? $this->createMetadataEducational($met, $doc, $dnode) : null;
|
||||
|
||||
return $dnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Metadata For File (How To).
|
||||
*
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
protected function createMetadataFile(CcIMetadataFile $met, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
$dnode = $doc->createElementNS($this->ccnamespaces['lom'], "lom");
|
||||
|
||||
!empty($xmlnode) ? $xmlnode->appendChild($dnode) : null;
|
||||
!empty($met->arrayeducational) ? $this->createMetadataEducational($met, $doc, $dnode) : null;
|
||||
|
||||
return $dnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create General Metadata (How To).
|
||||
*
|
||||
* @param object $met
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
protected function createMetadataGeneral($met, DOMDocument &$doc, $xmlnode)
|
||||
{
|
||||
$nd = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'general');
|
||||
|
||||
foreach ($met->arraygeneral as $name => $value) {
|
||||
!is_array($value) ? $value = [$value] : null;
|
||||
foreach ($value as $v) {
|
||||
if ($name != 'language' && $name != 'catalog' && $name != 'entry') {
|
||||
$nd2 = $doc->createElementNS($this->ccnamespaces['lomimscc'], $name);
|
||||
$nd3 = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'string', $v[1]);
|
||||
$ndatt = $doc->createAttribute('language');
|
||||
$ndatt->nodeValue = $v[0];
|
||||
$nd3->appendChild($ndatt);
|
||||
$nd2->appendChild($nd3);
|
||||
$nd->appendChild($nd2);
|
||||
} else {
|
||||
if ($name == 'language') {
|
||||
$nd2 = $doc->createElementNS($this->ccnamespaces['lomimscc'], $name, $v[0]);
|
||||
$nd->appendChild($nd2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($met->arraygeneral['catalog']) || !empty($met->arraygeneral['entry'])) {
|
||||
$nd2 = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'identifier');
|
||||
$nd->appendChild($nd2);
|
||||
if (!empty($met->arraygeneral['catalog'])) {
|
||||
$nd3 = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'catalog', $met->arraygeneral['catalog'][0][0]);
|
||||
$nd2->appendChild($nd3);
|
||||
}
|
||||
if (!empty($met->arraygeneral['entry'])) {
|
||||
$nd4 = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'entry', $met->arraygeneral['entry'][0][0]);
|
||||
$nd2->appendChild($nd4);
|
||||
}
|
||||
}
|
||||
|
||||
return $nd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Technical Metadata (How To).
|
||||
*
|
||||
* @param object $met
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
protected function createMetadataTechnical($met, DOMDocument &$doc, $xmlnode)
|
||||
{
|
||||
$nd = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'technical');
|
||||
$xmlnode->appendChild($nd);
|
||||
|
||||
foreach ($met->arraytech as $name => $value) {
|
||||
!is_array($value) ? $value = [$value] : null;
|
||||
foreach ($value as $v) {
|
||||
$nd2 = $doc->createElementNS($this->ccnamespaces['lomimscc'], $name, $v[0]);
|
||||
$nd->appendChild($nd2);
|
||||
}
|
||||
}
|
||||
|
||||
return $nd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Rights Metadata (How To).
|
||||
*
|
||||
* @param object $met
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
protected function createMetadataRights($met, DOMDocument &$doc, $xmlnode)
|
||||
{
|
||||
$nd = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'rights');
|
||||
|
||||
foreach ($met->arrayrights as $name => $value) {
|
||||
!is_array($value) ? $value = [$value] : null;
|
||||
foreach ($value as $v) {
|
||||
if ($name == 'description') {
|
||||
$nd2 = $doc->createElementNS($this->ccnamespaces['lomimscc'], $name);
|
||||
$nd3 = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'string', $v[1]);
|
||||
$ndatt = $doc->createAttribute('language');
|
||||
$ndatt->nodeValue = $v[0];
|
||||
$nd3->appendChild($ndatt);
|
||||
$nd2->appendChild($nd3);
|
||||
$nd->appendChild($nd2);
|
||||
} elseif ($name == 'copyrightAndOtherRestrictions' || $name == 'cost') {
|
||||
$nd2 = $doc->createElementNS($this->ccnamespaces['lomimscc'], $name);
|
||||
$nd3 = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'value', $v[0]);
|
||||
$nd2->appendChild($nd3);
|
||||
$nd->appendChild($nd2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $nd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Lifecycle Metadata (How To).
|
||||
*
|
||||
* @param object $met
|
||||
* @param object $met
|
||||
* @param object $xmlnode
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
protected function createMetadataLifecycle($met, DOMDocument &$doc, $xmlnode)
|
||||
{
|
||||
$nd = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'lifeCycle');
|
||||
$nd2 = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'contribute');
|
||||
|
||||
$nd->appendChild($nd2);
|
||||
$xmlnode->appendChild($nd);
|
||||
|
||||
foreach ($met->arraylifecycle as $name => $value) {
|
||||
!is_array($value) ? $value = [$value] : null;
|
||||
foreach ($value as $v) {
|
||||
if ($name == 'role') {
|
||||
$nd3 = $doc->createElementNS($this->ccnamespaces['lomimscc'], $name);
|
||||
$nd2->appendChild($nd3);
|
||||
$nd4 = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'value', $v[0]);
|
||||
$nd3->appendChild($nd4);
|
||||
} else {
|
||||
if ($name == 'date') {
|
||||
$nd3 = $doc->createElementNS($this->ccnamespaces['lomimscc'], $name);
|
||||
$nd2->appendChild($nd3);
|
||||
$nd4 = $doc->createElementNS($this->ccnamespaces['lomimscc'], 'dateTime', $v[0]);
|
||||
$nd3->appendChild($nd4);
|
||||
} else {
|
||||
$nd3 = $doc->createElementNS($this->ccnamespaces['lomimscc'], $name, $v[0]);
|
||||
$nd2->appendChild($nd3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $nd;
|
||||
}
|
||||
}
|
||||
122
main/common_cartridge/export/src/base/CcVersionBase.php
Normal file
122
main/common_cartridge/export/src/base/CcVersionBase.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_version_base.php under GNU/GPL license */
|
||||
|
||||
/**
|
||||
* Abstract Version Base class.
|
||||
*/
|
||||
abstract class CcVersionBase
|
||||
{
|
||||
public $resources = null;
|
||||
public $resourcesInd = null;
|
||||
public $organizations = null;
|
||||
public $ccversion = null;
|
||||
public $camversion = null;
|
||||
|
||||
protected $_generator = null;
|
||||
protected $ccnamespaces = [];
|
||||
protected $isrootmanifest = false;
|
||||
protected $manifestID = null;
|
||||
protected $organizationid = null;
|
||||
protected $metadata = null;
|
||||
protected $base = null;
|
||||
|
||||
public function getCcNamespaces()
|
||||
{
|
||||
return $this->ccnamespaces;
|
||||
}
|
||||
|
||||
public function createManifest(DOMDocument &$doc, $rootmanifestnode = null)
|
||||
{
|
||||
return $this->onCreate($doc, $rootmanifestnode);
|
||||
}
|
||||
|
||||
public function createResourceNode(CcIResource &$res, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
return $this->createResource($res, $doc, $xmlnode);
|
||||
}
|
||||
|
||||
public function createMetadataNode(&$met, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
return $this->createMetadataManifest($met, $doc, $xmlnode);
|
||||
}
|
||||
|
||||
public function createMetadataResourceNode(&$met, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
return $this->createMetadataResource($met, $doc, $xmlnode);
|
||||
}
|
||||
|
||||
public function createMetadataFileNode(&$met, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
return $this->createMetadataFile($met, $doc, $xmlnode);
|
||||
}
|
||||
|
||||
public function createOrganizationNode(CcIOrganization &$org, DOMDocument &$doc, $xmlnode = null)
|
||||
{
|
||||
return $this->createOrganization($org, $doc, $xmlnode);
|
||||
}
|
||||
|
||||
public function manifestID()
|
||||
{
|
||||
return $this->manifestID;
|
||||
}
|
||||
|
||||
public function setManifestID($id)
|
||||
{
|
||||
$this->manifestID = $id;
|
||||
}
|
||||
|
||||
public function getBase()
|
||||
{
|
||||
return $this->base;
|
||||
}
|
||||
|
||||
public function setBase($baseval)
|
||||
{
|
||||
$this->base = $baseval;
|
||||
}
|
||||
|
||||
public function importResources(DOMElement &$node, CcIManifest &$doc)
|
||||
{
|
||||
if (is_null($this->resources)) {
|
||||
$this->resources = [];
|
||||
}
|
||||
$nlist = $node->getElementsByTagNameNS($this->ccnamespaces['imscc'], 'resource');
|
||||
if (is_object($nlist)) {
|
||||
foreach ($nlist as $nd) {
|
||||
$sc = new CcResource($doc, $nd);
|
||||
$this->resources[$sc->identifier] = $sc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function importOrganizationItems(DOMElement &$node, CcIManifest &$doc)
|
||||
{
|
||||
if (is_null($this->organizations)) {
|
||||
$this->organizations = [];
|
||||
}
|
||||
$nlist = $node->getElementsByTagNameNS($this->ccnamespaces['imscc'], 'organization');
|
||||
if (is_object($nlist)) {
|
||||
foreach ($nlist as $nd) {
|
||||
$sc = new CcOrganization($nd, $doc);
|
||||
$this->organizations[$sc->identifier] = $sc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setGenerator($value)
|
||||
{
|
||||
$this->_generator = $value;
|
||||
}
|
||||
|
||||
abstract protected function onCreate(DOMDocument &$doc, $rootmanifestnode = null, $nmanifestID = null);
|
||||
|
||||
abstract protected function createMetadataManifest(CcIMetadataManifest $met, DOMDocument &$doc, $xmlnode = null);
|
||||
|
||||
abstract protected function createMetadataResource(CcIMetadataResource $met, DOMDocument &$doc, $xmlnode = null);
|
||||
|
||||
abstract protected function createMetadataFile(CcIMetadataFile $met, DOMDocument &$doc, $xmlnode = null);
|
||||
|
||||
abstract protected function createResource(CcIResource &$res, DOMDocument &$doc, $xmlnode = null);
|
||||
|
||||
abstract protected function createOrganization(CcIOrganization &$org, DOMDocument &$doc, $xmlnode = null);
|
||||
}
|
||||
269
main/common_cartridge/export/src/base/CssParser.php
Normal file
269
main/common_cartridge/export/src/base/CssParser.php
Normal file
@@ -0,0 +1,269 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/gral_lib/cssparser.php under GNU/GPL license */
|
||||
|
||||
class CssParser
|
||||
{
|
||||
private $css;
|
||||
private $html;
|
||||
|
||||
public function __construct($html = true)
|
||||
{
|
||||
$this->html = ($html != false);
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
unset($this->css);
|
||||
$this->css = [];
|
||||
if ($this->html) {
|
||||
$this->add("ADDRESS", "");
|
||||
$this->add("APPLET", "");
|
||||
$this->add("AREA", "");
|
||||
$this->add("A", "text-decoration : underline; color : Blue;");
|
||||
$this->add("A:visited", "color : Purple;");
|
||||
$this->add("BASE", "");
|
||||
$this->add("BASEFONT", "");
|
||||
$this->add("BIG", "");
|
||||
$this->add("BLOCKQUOTE", "");
|
||||
$this->add("BODY", "");
|
||||
$this->add("BR", "");
|
||||
$this->add("B", "font-weight: bold;");
|
||||
$this->add("CAPTION", "");
|
||||
$this->add("CENTER", "");
|
||||
$this->add("CITE", "");
|
||||
$this->add("CODE", "");
|
||||
$this->add("DD", "");
|
||||
$this->add("DFN", "");
|
||||
$this->add("DIR", "");
|
||||
$this->add("DIV", "");
|
||||
$this->add("DL", "");
|
||||
$this->add("DT", "");
|
||||
$this->add("EM", "");
|
||||
$this->add("FONT", "");
|
||||
$this->add("FORM", "");
|
||||
$this->add("H1", "");
|
||||
$this->add("H2", "");
|
||||
$this->add("H3", "");
|
||||
$this->add("H4", "");
|
||||
$this->add("H5", "");
|
||||
$this->add("H6", "");
|
||||
$this->add("HEAD", "");
|
||||
$this->add("HR", "");
|
||||
$this->add("HTML", "");
|
||||
$this->add("IMG", "");
|
||||
$this->add("INPUT", "");
|
||||
$this->add("ISINDEX", "");
|
||||
$this->add("I", "font-style: italic;");
|
||||
$this->add("KBD", "");
|
||||
$this->add("LINK", "");
|
||||
$this->add("LI", "");
|
||||
$this->add("MAP", "");
|
||||
$this->add("MENU", "");
|
||||
$this->add("META", "");
|
||||
$this->add("OL", "");
|
||||
$this->add("OPTION", "");
|
||||
$this->add("PARAM", "");
|
||||
$this->add("PRE", "");
|
||||
$this->add("P", "");
|
||||
$this->add("SAMP", "");
|
||||
$this->add("SCRIPT", "");
|
||||
$this->add("SELECT", "");
|
||||
$this->add("SMALL", "");
|
||||
$this->add("STRIKE", "");
|
||||
$this->add("STRONG", "");
|
||||
$this->add("STYLE", "");
|
||||
$this->add("SUB", "");
|
||||
$this->add("SUP", "");
|
||||
$this->add("TABLE", "");
|
||||
$this->add("TD", "");
|
||||
$this->add("TEXTAREA", "");
|
||||
$this->add("TH", "");
|
||||
$this->add("TITLE", "");
|
||||
$this->add("TR", "");
|
||||
$this->add("TT", "");
|
||||
$this->add("UL", "");
|
||||
$this->add("U", "text-decoration : underline;");
|
||||
$this->add("VAR", "");
|
||||
}
|
||||
}
|
||||
|
||||
public function setHTML($html)
|
||||
{
|
||||
$this->html = ($html != false);
|
||||
}
|
||||
|
||||
public function add($key, $codestr)
|
||||
{
|
||||
$key = strtolower($key);
|
||||
$codestr = strtolower($codestr);
|
||||
if (!isset($this->css[$key])) {
|
||||
$this->css[$key] = [];
|
||||
}
|
||||
$codes = explode(";", $codestr);
|
||||
if (count($codes) > 0) {
|
||||
$codekey = '';
|
||||
$codevalue = '';
|
||||
foreach ($codes as $code) {
|
||||
$code = trim($code);
|
||||
$this->assignValues(explode(":", $code), $codekey, $codevalue);
|
||||
if (strlen($codekey) > 0) {
|
||||
$this->css[$key][trim($codekey)] = trim($codevalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function get($key, $property)
|
||||
{
|
||||
$key = strtolower($key);
|
||||
$property = strtolower($property);
|
||||
$tag = '';
|
||||
$subtag = '';
|
||||
$class = '';
|
||||
$id = '';
|
||||
$this->assignValues(explode(":", $key), $tag, $subtag);
|
||||
$this->assignValues(explode(".", $tag), $tag, $class);
|
||||
$this->assignValues(explode("#", $tag), $tag, $id);
|
||||
$result = "";
|
||||
$_subtag = '';
|
||||
$_class = '';
|
||||
$_id = '';
|
||||
foreach ($this->css as $_tag => $value) {
|
||||
$this->assignValues(explode(":", $_tag), $_tag, $_subtag);
|
||||
$this->assignValues(explode(".", $_tag), $_tag, $_class);
|
||||
$this->assignValues(explode("#", $_tag), $_tag, $_id);
|
||||
|
||||
$tagmatch = (strcmp($tag, $_tag) == 0) | (strlen($_tag) == 0);
|
||||
$subtagmatch = (strcmp($subtag, $_subtag) == 0) | (strlen($_subtag) == 0);
|
||||
$classmatch = (strcmp($class, $_class) == 0) | (strlen($_class) == 0);
|
||||
$idmatch = (strcmp($id, $_id) == 0);
|
||||
|
||||
if ($tagmatch & $subtagmatch & $classmatch & $idmatch) {
|
||||
$temp = $_tag;
|
||||
if ((strlen($temp) > 0) & (strlen($_class) > 0)) {
|
||||
$temp .= ".".$_class;
|
||||
} elseif (strlen($temp) == 0) {
|
||||
$temp = ".".$_class;
|
||||
}
|
||||
if ((strlen($temp) > 0) & (strlen($_subtag) > 0)) {
|
||||
$temp .= ":".$_subtag;
|
||||
} elseif (strlen($temp) == 0) {
|
||||
$temp = ":".$_subtag;
|
||||
}
|
||||
if (isset($this->css[$temp][$property])) {
|
||||
$result = $this->css[$temp][$property];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getSection($key)
|
||||
{
|
||||
$key = strtolower($key);
|
||||
$tag = '';
|
||||
$subtag = '';
|
||||
$class = '';
|
||||
$id = '';
|
||||
$_subtag = '';
|
||||
$_class = '';
|
||||
$_id = '';
|
||||
|
||||
$this->assignValues(explode(":", $key), $tag, $subtag);
|
||||
$this->assignValues(explode(".", $tag), $tag, $class);
|
||||
$this->assignValues(explode("#", $tag), $tag, $id);
|
||||
$result = [];
|
||||
foreach ($this->css as $_tag => $value) {
|
||||
$this->assignValues(explode(":", $_tag), $_tag, $_subtag);
|
||||
$this->assignValues(explode(".", $_tag), $_tag, $_class);
|
||||
$this->assignValues(explode("#", $_tag), $_tag, $_id);
|
||||
|
||||
$tagmatch = (strcmp($tag, $_tag) == 0) | (strlen($_tag) == 0);
|
||||
$subtagmatch = (strcmp($subtag, $_subtag) == 0) | (strlen($_subtag) == 0);
|
||||
$classmatch = (strcmp($class, $_class) == 0) | (strlen($_class) == 0);
|
||||
$idmatch = (strcmp($id, $_id) == 0);
|
||||
|
||||
if ($tagmatch & $subtagmatch & $classmatch & $idmatch) {
|
||||
$temp = $_tag;
|
||||
if ((strlen($temp) > 0) & (strlen($_class) > 0)) {
|
||||
$temp .= ".".$_class;
|
||||
} elseif (strlen($temp) == 0) {
|
||||
$temp = ".".$_class;
|
||||
}
|
||||
if ((strlen($temp) > 0) & (strlen($_subtag) > 0)) {
|
||||
$temp .= ":".$_subtag;
|
||||
} elseif (strlen($temp) == 0) {
|
||||
$temp = ":".$_subtag;
|
||||
}
|
||||
foreach ($this->css[$temp] as $property => $value) {
|
||||
$result[$property] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function parseStr($str)
|
||||
{
|
||||
$this->clear();
|
||||
// Remove comments
|
||||
$str = preg_replace("/\/\*(.*)?\*\//Usi", "", $str);
|
||||
// Parse this damn csscode
|
||||
$parts = explode("}", $str);
|
||||
if (count($parts) > 0) {
|
||||
foreach ($parts as $part) {
|
||||
$keystr = '';
|
||||
$codestr = '';
|
||||
$this->assignValues(explode("{", $part), $keystr, $codestr);
|
||||
$keys = explode(",", trim($keystr));
|
||||
if (count($keys) > 0) {
|
||||
foreach ($keys as $key) {
|
||||
if (strlen($key) > 0) {
|
||||
$key = str_replace("\n", "", $key);
|
||||
$key = str_replace("\\", "", $key);
|
||||
$this->Add($key, trim($codestr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count($this->css) > 0;
|
||||
}
|
||||
|
||||
public function parse($filename)
|
||||
{
|
||||
$this->clear();
|
||||
if (file_exists($filename)) {
|
||||
return $this->parseStr(file_get_contents($filename));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getCSS()
|
||||
{
|
||||
$result = "";
|
||||
foreach ($this->css as $key => $values) {
|
||||
$result .= $key." {\n";
|
||||
foreach ($values as $key => $value) {
|
||||
$result .= " $key: $value;\n";
|
||||
}
|
||||
$result .= "}\n\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function assignValues($arr, &$val1, &$val2)
|
||||
{
|
||||
$n = count($arr);
|
||||
if ($n > 0) {
|
||||
$val1 = $arr[0];
|
||||
$val2 = ($n > 1) ? $arr[1] : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
470
main/common_cartridge/export/src/base/XMLGenericDocument.php
Normal file
470
main/common_cartridge/export/src/base/XMLGenericDocument.php
Normal file
@@ -0,0 +1,470 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/xmlbase.php under GNU/GPL license */
|
||||
|
||||
/**
|
||||
* Base XML class.
|
||||
*/
|
||||
class XMLGenericDocument
|
||||
{
|
||||
/**
|
||||
* Document.
|
||||
*
|
||||
* @var DOMDocument
|
||||
*/
|
||||
public $doc = null;
|
||||
/**
|
||||
* Xpath.
|
||||
*
|
||||
* @var DOMXPath
|
||||
*/
|
||||
protected $dxpath = null;
|
||||
protected $filename;
|
||||
private $charset;
|
||||
private $filepath;
|
||||
private $isloaded = false;
|
||||
private $arrayPrefixNS = [];
|
||||
private $isHtml = false;
|
||||
|
||||
public function __construct($ch = 'UTF-8', $validatenow = true)
|
||||
{
|
||||
$this->charset = $ch;
|
||||
$this->documentInit();
|
||||
$this->doc->validateOnParse = $validatenow;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->dxpath = null;
|
||||
$this->doc = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function safexml($value)
|
||||
{
|
||||
$result = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'),
|
||||
ENT_NOQUOTES,
|
||||
'UTF-8',
|
||||
false);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function viewXML()
|
||||
{
|
||||
return $this->doc->saveXML();
|
||||
}
|
||||
|
||||
public function registerNS($prefix, $nsuri)
|
||||
{
|
||||
$this->arrayPrefixNS[$prefix] = $nsuri;
|
||||
}
|
||||
|
||||
public function load($fname)
|
||||
{
|
||||
// Sine xml will remain loaded should the repeated load fail we should recreate document to be empty.
|
||||
$this->documentInit(false);
|
||||
$this->isloaded = $this->doc->load($fname);
|
||||
if ($this->isloaded) {
|
||||
$this->filename = $fname;
|
||||
$this->processPath();
|
||||
$this->isHtml = false;
|
||||
}
|
||||
|
||||
return $this->onLoad();
|
||||
}
|
||||
|
||||
public function loadUrl($url)
|
||||
{
|
||||
$this->documentInit();
|
||||
$this->isloaded = true;
|
||||
$this->doc->loadXML(file_get_contents($url));
|
||||
$this->isHtml = false;
|
||||
|
||||
return $this->onLoad();
|
||||
}
|
||||
|
||||
public function loadHTML($content)
|
||||
{
|
||||
$this->documentInit();
|
||||
$this->doc->validateOnParse = false;
|
||||
$this->isloaded = true;
|
||||
@$this->doc->loadHTML($content);
|
||||
$this->isHtml = true;
|
||||
|
||||
return $this->onLoad();
|
||||
}
|
||||
|
||||
public function loadXML($content)
|
||||
{
|
||||
$this->documentInit();
|
||||
$this->doc->validateOnParse = false;
|
||||
$this->isloaded = true;
|
||||
$this->doc->load($content);
|
||||
$this->isHtml = true;
|
||||
|
||||
return $this->onLoad();
|
||||
}
|
||||
|
||||
public function loadHTMLFile($fname)
|
||||
{
|
||||
// Sine xml will remain loaded should the repeated load fail
|
||||
// we should recreate document to be empty.
|
||||
$this->documentInit();
|
||||
$this->doc->validateOnParse = false;
|
||||
$this->isloaded = $this->doc->loadHTMLFile($fname);
|
||||
if ($this->isloaded) {
|
||||
$this->filename = $fname;
|
||||
$this->processPath();
|
||||
$this->isHtml = true;
|
||||
}
|
||||
|
||||
return $this->onLoad();
|
||||
}
|
||||
|
||||
public function loadXMLFile($fname)
|
||||
{
|
||||
// Sine xml will remain loaded should the repeated load fail
|
||||
// we should recreate document to be empty.
|
||||
$this->documentInit();
|
||||
$this->doc->validateOnParse = false;
|
||||
$this->isloaded = $this->doc->load($fname);
|
||||
if ($this->isloaded) {
|
||||
$this->filename = $fname;
|
||||
$this->processPath();
|
||||
$this->isHtml = true;
|
||||
}
|
||||
|
||||
return $this->onLoad();
|
||||
}
|
||||
|
||||
public function loadString($content)
|
||||
{
|
||||
$this->doc = new DOMDocument("1.0", $this->charset);
|
||||
$content = '<virtualtag>'.$content.'</virtualtag>';
|
||||
$this->doc->loadXML($content);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->saveTo($this->filename);
|
||||
}
|
||||
|
||||
public function saveTo($fname)
|
||||
{
|
||||
$status = false;
|
||||
if ($this->onSave()) {
|
||||
if ($this->isHtml) {
|
||||
$this->doc->saveHTMLFile($fname);
|
||||
} else {
|
||||
$this->doc->save($fname);
|
||||
}
|
||||
$this->filename = $fname;
|
||||
$this->processPath();
|
||||
$status = true;
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
return $this->doc->validate();
|
||||
}
|
||||
|
||||
public function attributeValue($path, $attrname, $node = null)
|
||||
{
|
||||
$this->chkxpath();
|
||||
$result = null;
|
||||
$resultlist = null;
|
||||
if (is_null($node)) {
|
||||
$resultlist = $this->dxpath->query($path);
|
||||
} else {
|
||||
$resultlist = $this->dxpath->query($path, $node);
|
||||
}
|
||||
if (is_object($resultlist) && ($resultlist->length > 0) && $resultlist->item(0)->hasAttribute($attrname)) {
|
||||
$result = $resultlist->item(0)->getAttribute($attrname);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's text value of the node based on xpath query.
|
||||
*
|
||||
* @param string $path
|
||||
* @param DOMNode $node
|
||||
* @param int $count
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function nodeValue($path, $node = null, $count = 1)
|
||||
{
|
||||
$nd = $this->node($path, $node, $count);
|
||||
|
||||
return $this->nodeTextValue($nd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's text value of the node.
|
||||
*
|
||||
* @param DOMNode $node
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function nodeTextValue($node)
|
||||
{
|
||||
$result = '';
|
||||
if (is_object($node)) {
|
||||
if ($node->hasChildNodes()) {
|
||||
$chnodesList = $node->childNodes;
|
||||
$types = [XML_TEXT_NODE, XML_CDATA_SECTION_NODE];
|
||||
foreach ($chnodesList as $chnode) {
|
||||
if (in_array($chnode->nodeType, $types)) {
|
||||
$result .= $chnode->wholeText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nodes from a path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param DOMNode $nd
|
||||
* @param int $count
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
public function node($path, $nd = null, $count = 1)
|
||||
{
|
||||
$result = null;
|
||||
$resultlist = $this->nodeList($path, $nd);
|
||||
if (is_object($resultlist) && ($resultlist->length > 0)) {
|
||||
$result = $resultlist->item($count - 1);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of nodes from a path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param DOMNode $node
|
||||
*
|
||||
* @return DOMNodeList
|
||||
*/
|
||||
public function nodeList($path, $node = null)
|
||||
{
|
||||
$this->chkxpath();
|
||||
$resultlist = null;
|
||||
if (is_null($node)) {
|
||||
$resultlist = $this->dxpath->query($path);
|
||||
} else {
|
||||
$resultlist = $this->dxpath->query($path, $node);
|
||||
}
|
||||
|
||||
return $resultlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new attribute.
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*
|
||||
* @return DOMAttr
|
||||
*/
|
||||
public function createAttributeNs($namespace, $name, $value = null)
|
||||
{
|
||||
$result = $this->doc->createAttributeNS($namespace, $name);
|
||||
if (!is_null($value)) {
|
||||
$result->nodeValue = $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new attribute.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*
|
||||
* @return DOMAttr
|
||||
*/
|
||||
public function createAttribute($name, $value = null)
|
||||
{
|
||||
$result = $this->doc->createAttribute($name);
|
||||
if (!is_null($value)) {
|
||||
$result->nodeValue = $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new node.
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
public function appendNewElementNs(DOMNode &$parentnode, $namespace, $name, $value = null)
|
||||
{
|
||||
$newnode = null;
|
||||
if (is_null($value)) {
|
||||
$newnode = $this->doc->createElementNS($namespace, $name);
|
||||
} else {
|
||||
$newnode = $this->doc->createElementNS($namespace, $name, $value);
|
||||
}
|
||||
|
||||
return $parentnode->appendChild($newnode);
|
||||
}
|
||||
|
||||
/**
|
||||
* New node with CDATA content.
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*/
|
||||
public function appendNewElementNsCdata(DOMNode &$parentnode, $namespace, $name, $value = null)
|
||||
{
|
||||
$newnode = $this->doc->createElementNS($namespace, $name);
|
||||
if (!is_null($value)) {
|
||||
$cdata = $this->doc->createCDATASection($value);
|
||||
$newnode->appendChild($cdata);
|
||||
}
|
||||
|
||||
return $parentnode->appendChild($newnode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new node.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
public function appendNewElement(DOMNode &$parentnode, $name, $value = null)
|
||||
{
|
||||
$newnode = null;
|
||||
if (is_null($value)) {
|
||||
$newnode = $this->doc->createElement($name);
|
||||
} else {
|
||||
$newnode = $this->doc->createElement($name, $value);
|
||||
}
|
||||
|
||||
return $parentnode->appendChild($newnode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new attribute.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
public function appendNewAttribute(DOMNode &$node, $name, $value = null)
|
||||
{
|
||||
return $node->appendChild($this->createAttribute($name, $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new attribute.
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
public function appendNewAttributeNs(DOMNode &$node, $namespace, $name, $value = null)
|
||||
{
|
||||
return $node->appendChild($this->createAttributeNs($namespace, $name, $value));
|
||||
}
|
||||
|
||||
public function fileName()
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
public function filePath()
|
||||
{
|
||||
return $this->filepath;
|
||||
}
|
||||
|
||||
public function resetXpath()
|
||||
{
|
||||
$this->dxpath = null;
|
||||
$this->chkxpath();
|
||||
}
|
||||
|
||||
protected function onLoad()
|
||||
{
|
||||
return $this->isloaded;
|
||||
}
|
||||
|
||||
protected function onSave()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function onCreate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function processPath()
|
||||
{
|
||||
$path_parts = pathinfo($this->filename);
|
||||
$this->filepath = array_key_exists('dirname', $path_parts) ? $path_parts['dirname']."/" : '';
|
||||
}
|
||||
|
||||
private function documentInit($withonCreate = true)
|
||||
{
|
||||
$hg = false;
|
||||
if ($this->isloaded) {
|
||||
$guardstate = $this->doc->validateOnParse;
|
||||
$hg = true;
|
||||
unset($this->dxpath);
|
||||
unset($this->doc);
|
||||
$this->isloaded = false;
|
||||
}
|
||||
$this->doc = new DOMDocument("1.0", $this->charset);
|
||||
$this->doc->strictErrorChecking = true;
|
||||
if ($hg) {
|
||||
$this->doc->validateOnParse = $guardstate;
|
||||
}
|
||||
$this->doc->formatOutput = true;
|
||||
$this->doc->preserveWhiteSpace = true;
|
||||
if ($withonCreate) {
|
||||
$this->onCreate();
|
||||
}
|
||||
}
|
||||
|
||||
private function chkxpath()
|
||||
{
|
||||
if (!isset($this->dxpath) || is_null($this->dxpath)) {
|
||||
$this->dxpath = new DOMXPath($this->doc);
|
||||
foreach ($this->arrayPrefixNS as $nskey => $nsuri) {
|
||||
$this->dxpath->registerNamespace($nskey, $nsuri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_converter_folder.php under GNU/GPL license */
|
||||
|
||||
class CcConverterFolder extends CcConverters
|
||||
{
|
||||
public function __construct(CcIItem &$item, CcIManifest &$manifest, $rootpath, $path)
|
||||
{
|
||||
$this->defaultfile = 'folder.xml';
|
||||
parent::__construct($item, $manifest, $rootpath, $path);
|
||||
}
|
||||
|
||||
public function convert($outdir, $objDocument)
|
||||
{
|
||||
$contextid = $objDocument['source_id'];
|
||||
$folder = api_get_path(SYS_COURSE_PATH).api_get_course_path($objDocument['course_code']).'/'.$objDocument['path'];
|
||||
$files = CcHelpers::handleStaticContent($this->manifest,
|
||||
$this->rootpath,
|
||||
$contextid,
|
||||
$outdir,
|
||||
true,
|
||||
$folder
|
||||
);
|
||||
$resvalue = null;
|
||||
foreach ($files as $values) {
|
||||
if ($values[2]) {
|
||||
$resvalue = $values[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$resitem = new CcItem();
|
||||
$resitem->identifierref = $resvalue;
|
||||
$resitem->title = $objDocument['title'];
|
||||
$this->item->addChildItem($resitem);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_converter_forum.php under GNU/GPL license */
|
||||
|
||||
class CcConverterForum extends CcConverters
|
||||
{
|
||||
public function __construct(CcIItem &$item, CcIManifest &$manifest, $rootpath, $path)
|
||||
{
|
||||
$this->ccType = CcVersion13::DISCUSSIONTOPIC;
|
||||
$this->defaultfile = 'forum.xml';
|
||||
$this->defaultname = 'discussion.xml';
|
||||
parent::__construct($item, $manifest, $rootpath, $path);
|
||||
}
|
||||
|
||||
public function convert($outdir, $item)
|
||||
{
|
||||
$rt = new CcForum();
|
||||
$title = $item['title'];
|
||||
$rt->setTitle($title);
|
||||
$text = $item['comment'];
|
||||
$deps = null;
|
||||
if (!empty($text)) {
|
||||
$contextid = $item['source_id'];
|
||||
$result = CcHelpers::processLinkedFiles($text,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$contextid,
|
||||
$outdir);
|
||||
$textformat = 'text/html';
|
||||
$rt->setText($result[0], $textformat);
|
||||
$deps = $result[1];
|
||||
}
|
||||
$this->store($rt, $outdir, $title, $deps);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_converter_page.php under GNU/GPL license */
|
||||
|
||||
class CcConverterPage extends CcConverters
|
||||
{
|
||||
public function __construct(CcIItem &$item, CcIManifest &$manifest, $rootpath, $path)
|
||||
{
|
||||
$this->ccType = CcVersion13::WEBCONTENT;
|
||||
$this->defaultfile = 'page.xml';
|
||||
$this->defaultname = uniqid().'.html';
|
||||
parent::__construct($item, $manifest, $rootpath, $path);
|
||||
}
|
||||
|
||||
public function convert($outdir, $objPage)
|
||||
{
|
||||
$rt = new CcPage();
|
||||
$title = $objPage['title'];
|
||||
$intro = '';
|
||||
$contextid = $objPage['source_id'];
|
||||
$pagecontent = $objPage['comment'];
|
||||
$rt->setTitle($title);
|
||||
$rawname = str_replace(' ', '_', strtolower(trim(Security::filter_filename($title))));
|
||||
|
||||
if (!empty($rawname)) {
|
||||
$this->defaultname = $rawname.".html";
|
||||
}
|
||||
|
||||
$result = CcHelpers::processLinkedFiles($pagecontent,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$contextid,
|
||||
$outdir,
|
||||
true);
|
||||
$rt->setContent($result[0]);
|
||||
$rt->setIntro($intro);
|
||||
//store everything
|
||||
$this->store($rt, $outdir, $title, $result[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_converter_quiz.php under GNU/GPL license */
|
||||
|
||||
class CcConverterQuiz extends CcConverters
|
||||
{
|
||||
public function __construct(CcIItem &$item, CcIManifest &$manifest, string $rootpath, string $path)
|
||||
{
|
||||
$this->ccType = CcVersion13::ASSESSMENT;
|
||||
$this->defaultfile = 'quiz.xml';
|
||||
$this->defaultname = Assesment13ResourceFile::DEAFULTNAME;
|
||||
parent::__construct($item, $manifest, $rootpath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a quiz to a CC XML file (.xml) in a subfolder of the whole CC archive.
|
||||
*
|
||||
* @param $outdir
|
||||
* @param $objQuizz
|
||||
*
|
||||
* @return bool true
|
||||
*/
|
||||
public function convert($outdir, $objQuizz): bool
|
||||
{
|
||||
$rt = new Assesment13ResourceFile();
|
||||
$title = $objQuizz['title'];
|
||||
$rt->setTitle($title);
|
||||
|
||||
// Metadata.
|
||||
$metadata = new CcAssesmentMetadata();
|
||||
$rt->setMetadata($metadata);
|
||||
$metadata->enableFeedback();
|
||||
$metadata->enableHints();
|
||||
$metadata->enableSolutions();
|
||||
// Attempts.
|
||||
$maxAttempts = $objQuizz['max_attempt'];
|
||||
|
||||
if ($maxAttempts > 0) {
|
||||
// Qti does not support number of specific attempts bigger than 5 (??)
|
||||
if ($maxAttempts > 5) {
|
||||
$maxAttempts = CcQtiValues::UNLIMITED;
|
||||
}
|
||||
$metadata->setMaxattempts($maxAttempts);
|
||||
}
|
||||
|
||||
// Time limit must be converted into minutes.
|
||||
$timelimit = $objQuizz['expired_time'];
|
||||
|
||||
if ($timelimit > 0) {
|
||||
$metadata->setTimelimit($timelimit);
|
||||
$metadata->enableLatesubmissions(false);
|
||||
}
|
||||
|
||||
$contextid = $objQuizz['source_id'];
|
||||
|
||||
$result = CcHelpers::processLinkedFiles($objQuizz['comment'],
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$contextid,
|
||||
$outdir);
|
||||
// Use exercise description, get it from $result[0] generated above.
|
||||
CcAssesmentHelper::addAssesmentDescription($rt, $result[0], CcQtiValues::HTMLTYPE);
|
||||
|
||||
// Section.
|
||||
$section = new CcAssesmentSection();
|
||||
$rt->setSection($section);
|
||||
// Process the actual questions.
|
||||
$ndeps = CcAssesmentHelper::processQuestions($objQuizz,
|
||||
$this->manifest,
|
||||
$section,
|
||||
$this->rootpath,
|
||||
$contextid,
|
||||
$outdir
|
||||
);
|
||||
|
||||
if ($ndeps === false) {
|
||||
// No exportable questions in quiz or quiz has no questions
|
||||
// so just skip it.
|
||||
return true;
|
||||
}
|
||||
// Store any additional dependencies.
|
||||
$deps = array_merge($result[1], $ndeps);
|
||||
|
||||
// Store everything.
|
||||
$this->store($rt, $outdir, $title, $deps);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_converter_resource.php under GNU/GPL license */
|
||||
|
||||
class CcConverterResource extends CcConverters
|
||||
{
|
||||
public function __construct(CcIItem &$item, CcIManifest &$manifest, $rootpath, $path)
|
||||
{
|
||||
$this->ccType = CcVersion13::WEBCONTENT;
|
||||
$this->defaultfile = 'resource.xml';
|
||||
parent::__construct($item, $manifest, $rootpath, $path);
|
||||
}
|
||||
|
||||
public function convert($outdir, $objResource)
|
||||
{
|
||||
$title = $objResource['title'];
|
||||
$contextid = $objResource['source_id'];
|
||||
$docfilepath = null;
|
||||
if (isset($objResource['path'])) {
|
||||
$docfilepath = api_get_path(SYS_COURSE_PATH).api_get_course_path($objResource['course_code']).DIRECTORY_SEPARATOR.$objResource['path'];
|
||||
}
|
||||
|
||||
$files = CcHelpers::handleResourceContent($this->manifest,
|
||||
$this->rootpath,
|
||||
$contextid,
|
||||
$outdir,
|
||||
true,
|
||||
$docfilepath);
|
||||
|
||||
$deps = null;
|
||||
$resvalue = null;
|
||||
foreach ($files as $values) {
|
||||
if ($values[2]) {
|
||||
$resvalue = $values[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$resitem = new CcItem();
|
||||
$resitem->identifierref = $resvalue;
|
||||
$resitem->title = $title;
|
||||
$this->item->addChildItem($resitem);
|
||||
|
||||
// Checking the visibility.
|
||||
$this->manifest->updateInstructoronly($resvalue, !$this->isVisible());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_converter_url.php under GNU/GPL license */
|
||||
|
||||
class CcConverterUrl extends CcConverters
|
||||
{
|
||||
public function __construct(CcIItem &$item, CcIManifest &$manifest, $rootpath, $path)
|
||||
{
|
||||
$this->ccType = CcVersion13::WEBLINK;
|
||||
$this->defaultfile = 'url.xml';
|
||||
$this->defaultname = 'weblink.xml';
|
||||
parent::__construct($item, $manifest, $rootpath, $path);
|
||||
}
|
||||
|
||||
public function convert($outdir, $objLink)
|
||||
{
|
||||
$rt = new CcWebLink();
|
||||
$title = $objLink['title'];
|
||||
$rt->setTitle($title);
|
||||
$url = $objLink['url'];
|
||||
if (!empty($url)) {
|
||||
$rt->setUrl($url, $objLink['target']);
|
||||
}
|
||||
$this->store($rt, $outdir, $title);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
18
main/common_cartridge/export/src/interfaces/CcIItem.php
Normal file
18
main/common_cartridge/export/src/interfaces/CcIItem.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* CC Item Interface.
|
||||
*/
|
||||
interface CcIItem
|
||||
{
|
||||
public function addChildItem(CcIItem &$item);
|
||||
|
||||
public function attachResource($res); // can be object or value
|
||||
|
||||
public function hasChildItems();
|
||||
|
||||
public function attrValue(&$nod, $name, $ns = null);
|
||||
|
||||
public function processItem(&$node, &$doc);
|
||||
}
|
||||
30
main/common_cartridge/export/src/interfaces/CcIManifest.php
Normal file
30
main/common_cartridge/export/src/interfaces/CcIManifest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* CC Manifest Interface.
|
||||
*/
|
||||
interface CcIManifest
|
||||
{
|
||||
public function onCreate();
|
||||
|
||||
public function onLoad();
|
||||
|
||||
public function onSave();
|
||||
|
||||
public function addNewOrganization(CcIOrganization &$org);
|
||||
|
||||
public function getResources();
|
||||
|
||||
public function getResourceList();
|
||||
|
||||
public function addResource(CcIResource $res, $identifier = null, $type = 'webcontent');
|
||||
|
||||
public function addMetadataManifest(CcIMetadataManifest $met);
|
||||
|
||||
public function addMetadataResource(CcIMetadataResource $met, $identifier);
|
||||
|
||||
public function addMetadataFile(CcIMetadataFile $met, $identifier, $filename);
|
||||
|
||||
public function putNodes();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* CC Metadata File Interface.
|
||||
*/
|
||||
interface CcIMetadataFile
|
||||
{
|
||||
public function addMetadataFileEducational($obj);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* CC Metadata Manifest Interface.
|
||||
*/
|
||||
interface CcIMetadataManifest
|
||||
{
|
||||
public function addMetadataGeneral($obj);
|
||||
|
||||
public function addMetadataTechnical($obj);
|
||||
|
||||
public function addMetadataRights($obj);
|
||||
|
||||
public function addMetadataLifecycle($obj);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* CC Metadata Resource Interface.
|
||||
*/
|
||||
interface CcIMetadataResource
|
||||
{
|
||||
public function addMetadataResourceEducational($obj);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* CC Organization Interface.
|
||||
*/
|
||||
interface CcIOrganization
|
||||
{
|
||||
public function addItem(CcIItem &$item);
|
||||
|
||||
public function hasItems();
|
||||
|
||||
public function attrValue(&$nod, $name, $ns = null);
|
||||
|
||||
public function processOrganization(&$node, &$doc);
|
||||
}
|
||||
16
main/common_cartridge/export/src/interfaces/CcIResource.php
Normal file
16
main/common_cartridge/export/src/interfaces/CcIResource.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* CC Resource Interface.
|
||||
*/
|
||||
interface CcIResource
|
||||
{
|
||||
public function getAttrValue(&$nod, $name, $ns = null);
|
||||
|
||||
public function addResource($fname, $location = '');
|
||||
|
||||
public function importResource(DOMElement &$node, CcIManifest &$doc);
|
||||
|
||||
public function processResource($manifestroot, &$fname, $folder);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class Assesment13ResourceFile extends Assesment1ResourceFile
|
||||
{
|
||||
protected $ccnsnames = ['xmlns' => 'http://www.imsglobal.org/profile/cc/ccv1p3/ccv1p3_qtiasiv1p2p1_v1p0.xsd'];
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class Assesment1ResourceFile extends CcGeneralFile
|
||||
{
|
||||
public const DEAFULTNAME = 'assessment.xml';
|
||||
|
||||
protected $rootns = 'xmlns';
|
||||
protected $rootname = CcQtiTags::QUESTESTINTEROP;
|
||||
protected $ccnamespaces = ['xmlns' => 'http://www.imsglobal.org/xsd/ims_qtiasiv1p2',
|
||||
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance', ];
|
||||
protected $ccnsnames = ['xmlns' => 'http://www.imsglobal.org/profile/cc/ccv1p0/derived_schema/domainProfile_4/ims_qtiasiv1p2_localised.xsd'];
|
||||
protected $assessmentTitle = 'Untitled';
|
||||
protected $metadata = null;
|
||||
protected $rubric = null;
|
||||
protected $presentationMaterial = null;
|
||||
protected $section = null;
|
||||
|
||||
public function setMetadata(CcAssesmentMetadata $object)
|
||||
{
|
||||
$this->metadata = $object;
|
||||
}
|
||||
|
||||
public function setRubric(CcAssesmentRubricBase $object)
|
||||
{
|
||||
$this->rubric = $object;
|
||||
}
|
||||
|
||||
public function setPresentationMaterial(CcAssesmentPresentationMaterialBase $object)
|
||||
{
|
||||
$this->presentationMaterial = $object;
|
||||
}
|
||||
|
||||
public function setSection(CcAssesmentSection $object)
|
||||
{
|
||||
$this->section = $object;
|
||||
}
|
||||
|
||||
public function setTitle($value)
|
||||
{
|
||||
$this->assessmentTitle = self::safexml($value);
|
||||
}
|
||||
|
||||
protected function onSave()
|
||||
{
|
||||
$rns = $this->ccnamespaces[$this->rootns];
|
||||
//root assesment element - required
|
||||
$assessment = $this->appendNewElementNs($this->root, $rns, CcQtiTags::ASSESSMENT);
|
||||
$this->appendNewAttributeNs($assessment, $rns, CcQtiTags::IDENT, CcHelpers::uuidgen('QDB_'));
|
||||
$this->appendNewAttributeNs($assessment, $rns, CcQtiTags::TITLE, $this->assessmentTitle);
|
||||
|
||||
//metadata - optional
|
||||
if (!empty($this->metadata)) {
|
||||
$this->metadata->generate($this, $assessment, $rns);
|
||||
}
|
||||
|
||||
//rubric - optional
|
||||
if (!empty($this->rubric)) {
|
||||
$this->rubric->generate($this, $assessment, $rns);
|
||||
}
|
||||
|
||||
//presentation_material - optional
|
||||
if (!empty($this->presentationMaterial)) {
|
||||
$this->presentationMaterial->generate($this, $assessment, $rns);
|
||||
}
|
||||
|
||||
//section - required
|
||||
if (!empty($this->section)) {
|
||||
$this->section->generate($this, $assessment, $rns);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentAltmaterial extends CcAssesmentMaterialBase
|
||||
{
|
||||
public function __construct($value = null)
|
||||
{
|
||||
$this->setSettingWns(CcQtiTags::XML_LANG, CcXmlNamespace::XML);
|
||||
$this->tagname = CcQtiTags::ALTMATERIAL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentDecvartype extends CcQuestionMetadataBase
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::VARNAME, CcQtiValues::SCORE);
|
||||
$this->setSetting(CcQtiTags::VARTYPE, CcQtiValues::INTEGER);
|
||||
$this->setSetting(CcQtiTags::MINVALUE);
|
||||
$this->setSetting(CcQtiTags::MAXVALUE);
|
||||
}
|
||||
|
||||
public function setVartype($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::VARTYPE, $value);
|
||||
}
|
||||
|
||||
public function setLimits($min = null, $max = null)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::MINVALUE, $min);
|
||||
$this->setSetting(CcQtiTags::MAXVALUE, $max);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::DECVAR);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentFlowLabeltype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $flowLabel = null;
|
||||
protected $responseLabel = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::T_CLASS);
|
||||
}
|
||||
|
||||
public function setClass($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::T_CLASS, $value);
|
||||
}
|
||||
|
||||
public function setFlowLabel(CcAssesmentFlowLabeltype $object)
|
||||
{
|
||||
$this->flowLabel = $object;
|
||||
}
|
||||
|
||||
public function setResponseLabel(CcAssesmentResponseLabeltype $object)
|
||||
{
|
||||
$this->responseLabel = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::FLOW_LABEL);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->material)) {
|
||||
$this->material->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->materialRef)) {
|
||||
$this->materialRef->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->responseLabel)) {
|
||||
$this->responseLabel->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->flowLabel)) {
|
||||
$this->flowLabel->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentFlowMatBase extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $mattag = null;
|
||||
|
||||
public function __construct($value = null)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::T_CLASS);
|
||||
}
|
||||
|
||||
public function setFlowMat(CcAssesmentFlowMatBase $object)
|
||||
{
|
||||
$this->setTagValue($object);
|
||||
}
|
||||
|
||||
public function setMaterial(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->setTagValue($object);
|
||||
}
|
||||
|
||||
public function setMaterialRef(CcAssesmentMatref $object)
|
||||
{
|
||||
$this->setTagValue($object);
|
||||
}
|
||||
|
||||
public function setClass($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::T_CLASS, $value);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::FLOW_MAT);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
if (!empty($this->mattag)) {
|
||||
$this->mattag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
protected function setTagValue($object)
|
||||
{
|
||||
$this->mattag = $object;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentFlowMattype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $material = null;
|
||||
protected $materialRef = null;
|
||||
protected $flowMat = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::T_CLASS);
|
||||
}
|
||||
|
||||
public function setClass($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::T_CLASS, $value);
|
||||
}
|
||||
|
||||
public function setMaterial(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->material = $object;
|
||||
}
|
||||
|
||||
public function setMaterialRef(CcAssesmentResponseMatref $object)
|
||||
{
|
||||
$this->materialRef = $object;
|
||||
}
|
||||
|
||||
public function setFlowMat(CcAssesmentFlowMattype $object)
|
||||
{
|
||||
$this->flowMat = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::FLOW_MAT);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->flowMat)) {
|
||||
$this->flowMat->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->material)) {
|
||||
$this->material->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->materialRef)) {
|
||||
$this->materialRef->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentFlowtype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $flow = null;
|
||||
protected $material = null;
|
||||
protected $materialRef = null;
|
||||
protected $responseLid = null;
|
||||
protected $responseStr = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::T_CLASS);
|
||||
}
|
||||
|
||||
public function setClass($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::T_CLASS, $value);
|
||||
}
|
||||
|
||||
public function setFlow(CcAssesmentFlowtype $object)
|
||||
{
|
||||
$this->flow = $object;
|
||||
}
|
||||
|
||||
public function setMaterial(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->material = $object;
|
||||
}
|
||||
|
||||
public function setMaterialRef(CcAssesmentResponseMatref $object)
|
||||
{
|
||||
$this->materialRef = $object;
|
||||
}
|
||||
|
||||
public function setResponseLid(CcResponseLidtype $object)
|
||||
{
|
||||
$this->responseLid = $object;
|
||||
}
|
||||
|
||||
public function setResponseStr(CcAssesmentResponseStrtype $object)
|
||||
{
|
||||
$this->responseStr = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::FLOW);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->flow)) {
|
||||
$this->flow->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->material)) {
|
||||
$this->material->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->responseLid)) {
|
||||
$this->responseLid->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->responseStr)) {
|
||||
$this->responseStr->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
abstract class CcAssesmentHelper
|
||||
{
|
||||
public static $correctFb = null;
|
||||
public static $incorrectFb = null;
|
||||
|
||||
public static function addFeedback($qitem, $content, $contentType, $ident)
|
||||
{
|
||||
if (empty($content)) {
|
||||
return false;
|
||||
}
|
||||
$qitemfeedback = new CcAssesmentItemfeedbacktype();
|
||||
$qitem->addItemfeedback($qitemfeedback);
|
||||
if (!empty($ident)) {
|
||||
$qitemfeedback->setIdent($ident);
|
||||
}
|
||||
$qflowmat = new CcAssesmentFlowMattype();
|
||||
$qitemfeedback->setFlowMat($qflowmat);
|
||||
$qmaterialfb = new CcAssesmentMaterial();
|
||||
$qflowmat->setMaterial($qmaterialfb);
|
||||
$qmattext = new CcAssesmentMattext();
|
||||
$qmaterialfb->setMattext($qmattext);
|
||||
$qmattext->setContent($content, $contentType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function addAnswer($qresponseChoice, $content, $contentType)
|
||||
{
|
||||
$qresponseLabel = new CcAssesmentResponseLabeltype();
|
||||
$qresponseChoice->addResponseLabel($qresponseLabel);
|
||||
$qrespmaterial = new CcAssesmentMaterial();
|
||||
$qresponseLabel->setMaterial($qrespmaterial);
|
||||
$qrespmattext = new CcAssesmentMattext();
|
||||
$qrespmaterial->setMattext($qrespmattext);
|
||||
$qrespmattext->setContent($content, $contentType);
|
||||
|
||||
return $qresponseLabel;
|
||||
}
|
||||
|
||||
public static function addResponseCondition($node, $title, $ident, $feedbackRefid, $respident)
|
||||
{
|
||||
$qrespcondition = new CcAssesmentRespconditiontype();
|
||||
$node->addRespcondition($qrespcondition);
|
||||
//define rest of the conditions
|
||||
$qconditionvar = new CcAssignmentConditionvar();
|
||||
$qrespcondition->setConditionvar($qconditionvar);
|
||||
$qvarequal = new CcAssignmentConditionvarVarequaltype($ident);
|
||||
$qvarequal->enableCase();
|
||||
$qconditionvar->setVarequal($qvarequal);
|
||||
$qvarequal->setRespident($respident);
|
||||
$qdisplayfeedback = new CcAssignmentDisplayfeedbacktype();
|
||||
$qrespcondition->addDisplayfeedback($qdisplayfeedback);
|
||||
$qdisplayfeedback->setFeedbacktype(CcQtiValues::RESPONSE);
|
||||
$qdisplayfeedback->setLinkrefid($feedbackRefid);
|
||||
}
|
||||
|
||||
public static function addAssesmentDescription($rt, $content, $contenttype)
|
||||
{
|
||||
if (empty($rt) || empty($content)) {
|
||||
return;
|
||||
}
|
||||
$activity_rubric = new CcAssesmentRubricBase();
|
||||
$rubric_material = new CcAssesmentMaterial();
|
||||
$activity_rubric->setMaterial($rubric_material);
|
||||
$rubric_mattext = new CcAssesmentMattext();
|
||||
$rubric_material->setLabel('Summary');
|
||||
$rubric_material->setMattext($rubric_mattext);
|
||||
$rubric_mattext->setContent($content, $contenttype);
|
||||
$rt->setRubric($activity_rubric);
|
||||
}
|
||||
|
||||
public static function addRespcondition($node, $title, $feedbackRefid, $gradeValue = null, $continue = false)
|
||||
{
|
||||
$qrespcondition = new CcAssesmentRespconditiontype();
|
||||
$qrespcondition->setTitle($title);
|
||||
$node->addRespcondition($qrespcondition);
|
||||
$qrespcondition->enableContinue($continue);
|
||||
//Add setvar if grade present
|
||||
if ($gradeValue !== null) {
|
||||
$qsetvar = new CcAssignmentSetvartype($gradeValue);
|
||||
$qrespcondition->addSetvar($qsetvar);
|
||||
}
|
||||
//define the condition for success
|
||||
$qconditionvar = new CcAssignmentConditionvar();
|
||||
$qrespcondition->setConditionvar($qconditionvar);
|
||||
$qother = new CcAssignmentConditionvarOthertype();
|
||||
$qconditionvar->setOther($qother);
|
||||
$qdisplayfeedback = new CcAssignmentDisplayfeedbacktype();
|
||||
$qrespcondition->addDisplayfeedback($qdisplayfeedback);
|
||||
$qdisplayfeedback->setFeedbacktype(CcQtiValues::RESPONSE);
|
||||
$qdisplayfeedback->setLinkrefid($feedbackRefid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter description here ...
|
||||
*
|
||||
* @param XMLGenericDocument $qdoc
|
||||
* @param unknown_type $manifest
|
||||
* @param cc_assesment_section $section
|
||||
* @param unknown_type $rootpath
|
||||
* @param unknown_type $contextid
|
||||
* @param string $outdir
|
||||
*/
|
||||
public static function processQuestions(&$objQuizz, &$manifest, CcAssesmentSection &$section, $rootpath, $contextid, $outdir)
|
||||
{
|
||||
PkgResourceDependencies::instance()->reset();
|
||||
$questioncount = 0;
|
||||
foreach ($objQuizz['questions'] as $question) {
|
||||
$qtype = $question->quiz_type;
|
||||
/* Question type comes from the c_quiz_question.type column.
|
||||
* You can find the different types defined in api.lib.php.
|
||||
* Look for UNIQUE_ANSWER as the first constant defined
|
||||
* 1 : Unique Answer (Multiple choice, single response)
|
||||
* 2 : Multiple Answers (Multiple choice, multiple response)
|
||||
* 5 : Free Answer ("essay" in CC13)
|
||||
*/
|
||||
$questionProcessor = null;
|
||||
switch ($qtype) {
|
||||
case UNIQUE_ANSWER:
|
||||
try {
|
||||
$questionProcessor = new CcAssesmentQuestionMultichoice($objQuizz, $objQuizz['questions'], $manifest, $section, $question, $rootpath, $contextid, $outdir);
|
||||
$questionProcessor->generate();
|
||||
$questioncount++;
|
||||
} catch (RuntimeException $e) {
|
||||
error_log($e->getMessage().' in question of test '.$objQuizz['title']);
|
||||
continue 2;
|
||||
}
|
||||
break;
|
||||
case MULTIPLE_ANSWER:
|
||||
try {
|
||||
$questionProcessor = new CcAssesmentQuestionMultichoiceMultiresponse($objQuizz, $objQuizz['questions'], $manifest, $section, $question, $rootpath, $contextid, $outdir);
|
||||
$questionProcessor->generate();
|
||||
$questioncount++;
|
||||
} catch (RuntimeException $e) {
|
||||
error_log($e->getMessage().' in question of test '.$objQuizz['title']);
|
||||
continue 2;
|
||||
}
|
||||
break;
|
||||
case FILL_IN_BLANKS:
|
||||
try {
|
||||
$questionProcessor = new CcAssesmentQuestionFib($objQuizz, $objQuizz['questions'], $manifest, $section, $question, $rootpath, $contextid, $outdir);
|
||||
$questionProcessor->generate();
|
||||
$questioncount++;
|
||||
} catch (RuntimeException $e) {
|
||||
error_log($e->getMessage().' in question of test '.$objQuizz['title']);
|
||||
continue 2;
|
||||
}
|
||||
break;
|
||||
case FREE_ANSWER:
|
||||
try {
|
||||
$questionProcessor = new CcAssesmentQuestionEssay($objQuizz, $objQuizz['questions'], $manifest, $section, $question, $rootpath, $contextid, $outdir);
|
||||
$questionProcessor->generate();
|
||||
$questioncount++;
|
||||
} catch (RuntimeException $e) {
|
||||
error_log($e->getMessage().' in question of test '.$objQuizz['title']);
|
||||
continue 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//return dependencies
|
||||
return ($questioncount == 0) ? false : PkgResourceDependencies::instance()->getDeps();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentItemfeedbacHinttype extends CcAssesmentItemfeedbackShintypeBase
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->tagname = CcQtiTags::HINT;
|
||||
}
|
||||
|
||||
public function addHintmaterial(CcAssesmentItemfeedbackHintmaterial $object)
|
||||
{
|
||||
$this->items[] = $object;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentItemfeedbackHintmaterial extends CcAssesmentItemfeedbackShintmaterialBase
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->tagname = CcQtiTags::HINT;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentItemfeedbackShintmaterialBase extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $tagname = null;
|
||||
protected $flowMats = [];
|
||||
protected $materials = [];
|
||||
|
||||
public function addFlowMat(CcAssesmentFlowMattype $object)
|
||||
{
|
||||
$this->flowMats[] = $object;
|
||||
}
|
||||
|
||||
public function add_material(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->materials[] = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, $this->tagname);
|
||||
|
||||
if (!empty($this->flowMats)) {
|
||||
foreach ($this->flowMats as $flowMat) {
|
||||
$flowMat->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->materials)) {
|
||||
foreach ($this->materials as $material) {
|
||||
$material->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentItemfeedbackShintypeBase extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $tagname = null;
|
||||
protected $items = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::FEEDBACKSTYLE, CcQtiValues::COMPLETE);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, $this->tagname);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->items)) {
|
||||
foreach ($this->items as $telement) {
|
||||
$telement->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentItemfeedbackSolutionmaterial extends CcAssesmentItemfeedbackShintmaterialBase
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->tagname = CcQtiTags::SOLUTIONMATERIAL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentItemfeedbackSolutiontype extends CcAssesmentItemfeedbackShintypeBase
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->tagname = CcQtiTags::SOLUTION;
|
||||
}
|
||||
|
||||
public function add_solutionmaterial(CcAssesmentItemfeedbackSolutionmaterial $object)
|
||||
{
|
||||
$this->items[] = $object;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentItemfeedbacktype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $flowMat = null;
|
||||
protected $material = null;
|
||||
protected $solution = null;
|
||||
protected $hint = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::IDENT, CcHelpers::uuidgen('I_'));
|
||||
$this->setSetting(CcQtiTags::TITLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setIdent($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::IDENT, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setTitle($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::TITLE, $value);
|
||||
}
|
||||
|
||||
public function setFlowMat(CcAssesmentFlowMattype $object)
|
||||
{
|
||||
$this->flowMat = $object;
|
||||
}
|
||||
|
||||
public function setMaterial(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->material = $object;
|
||||
}
|
||||
|
||||
public function set_solution(CcAssesmentItemfeedbackSolutiontype $object)
|
||||
{
|
||||
$this->solution = $object;
|
||||
}
|
||||
|
||||
public function set_hint($object)
|
||||
{
|
||||
$this->hint = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::ITEMFEEDBACK);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->flowMat) && empty($this->material)) {
|
||||
$this->flowMat->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->material) && empty($this->flowMat)) {
|
||||
$this->material->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->solution)) {
|
||||
$this->solution->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->itemfeedback)) {
|
||||
$this->itemfeedback->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentItemmetadata extends CcQuestionMetadataBase
|
||||
{
|
||||
public function addMetadata($object)
|
||||
{
|
||||
$this->metadata[] = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::ITEMMETADATA);
|
||||
if (!empty($this->metadata)) {
|
||||
foreach ($this->metadata as $metaitem) {
|
||||
$metaitem->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentMatbreak
|
||||
{
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$doc->appendNewElementNs($item, $namespace, CcQtiTags::MATBREAK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentMaterial extends CcAssesmentMaterialBase
|
||||
{
|
||||
protected $altmaterial = null;
|
||||
|
||||
public function __construct($value = null)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::LABEL);
|
||||
$this->setSettingWns(CcQtiTags::XML_LANG, CcXmlNamespace::XML);
|
||||
$this->tagname = CcQtiTags::MATERIAL;
|
||||
}
|
||||
|
||||
public function setLabel($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::LABEL, $value);
|
||||
}
|
||||
|
||||
public function setAltmaterial(CcAssesmentAltmaterial $object)
|
||||
{
|
||||
$this->altmaterial = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$material = parent::generate($doc, $item, $namespace);
|
||||
if (!empty($this->altmaterial)) {
|
||||
$this->altmaterial->generate($doc, $material, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
abstract class CcAssesmentMaterialBase extends CcQuestionMetadataBase
|
||||
{
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected $mattag = null;
|
||||
protected $tagname = null;
|
||||
|
||||
public function setMattext(CcAssesmentMattext $object)
|
||||
{
|
||||
$this->setTagValue($object);
|
||||
}
|
||||
|
||||
public function setMatref(CcAssesmentMatref $object)
|
||||
{
|
||||
$this->setTagValue($object);
|
||||
}
|
||||
|
||||
public function setMatbreak(CcAssesmentMatbreak $object)
|
||||
{
|
||||
$this->setTagValue($object);
|
||||
}
|
||||
|
||||
public function setLang($value)
|
||||
{
|
||||
$this->setSettingWns(CcQtiTags::XML_LANG, CcXmlNamespace::XML, $value);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$material = $doc->appendNewElementNs($item, $namespace, $this->tagname);
|
||||
$this->generateAttributes($doc, $material, $namespace);
|
||||
if (!empty($this->mattag)) {
|
||||
$this->mattag->generate($doc, $material, $namespace);
|
||||
}
|
||||
|
||||
return $material;
|
||||
}
|
||||
|
||||
protected function setTagValue($object)
|
||||
{
|
||||
$this->mattag = $object;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentMatref
|
||||
{
|
||||
protected $linkref = null;
|
||||
|
||||
public function __construct($linkref)
|
||||
{
|
||||
$this->linkref = $linkref;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::MATREF, $this->linkref);
|
||||
$doc->appendNewAttributeNs($node, $namespace, CcQtiTags::LINKREFID, $this->linkref);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentMattext extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $value = null;
|
||||
|
||||
public function __construct($value = null)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::TEXTTYPE, CcQtiValues::TEXTTYPE);
|
||||
$this->setSetting(CcQtiTags::CHARSET); //, 'ascii-us');
|
||||
$this->setSetting(CcQtiTags::LABEL);
|
||||
$this->setSetting(CcQtiTags::URI);
|
||||
$this->setSetting(CcQtiTags::WIDTH);
|
||||
$this->setSetting(CcQtiTags::HEIGHT);
|
||||
$this->setSetting(CcQtiTags::X0);
|
||||
$this->setSetting(CcQtiTags::Y0);
|
||||
$this->setSettingWns(CcQtiTags::XML_LANG, CcXmlNamespace::XML);
|
||||
$this->setSettingWns(CcQtiTags::XML_SPACE, CcXmlNamespace::XML); //, 'default');
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function setLabel($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::LABEL, $value);
|
||||
}
|
||||
|
||||
public function setUri($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::URI, $value);
|
||||
}
|
||||
|
||||
public function setWidthHeight($width = null, $height = null)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::WIDTH, $width);
|
||||
$this->setSetting(CcQtiTags::HEIGHT, $height);
|
||||
}
|
||||
|
||||
public function setCoor($x = null, $y = null)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::X0, $x);
|
||||
$this->setSetting(CcQtiTags::Y0, $y);
|
||||
}
|
||||
|
||||
public function setLang($lang = null)
|
||||
{
|
||||
$this->setSettingWns(CcQtiTags::XML_LANG, CcXmlNamespace::XML, $lang);
|
||||
}
|
||||
|
||||
public function setContent($content, $type = CcQtiValues::TEXTTYPE, $charset = null)
|
||||
{
|
||||
$this->value = $content;
|
||||
$this->setSetting(CcQtiTags::TEXTTYPE, $type);
|
||||
$this->setSetting(CcQtiTags::CHARSET, $charset);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$mattext = $doc->appendNewElementNsCdata($item, $namespace, CcQtiTags::MATTEXT, $this->value);
|
||||
$this->generateAttributes($doc, $mattext, $namespace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentMetadata extends CcQuestionMetadataBase
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
//prepared default values
|
||||
$this->setSetting(CcQtiMetadata::CC_PROFILE, CcQtiValues::EXAM_PROFILE);
|
||||
$this->setSetting(CcQtiMetadata::QMD_ASSESSMENTTYPE, CcQtiValues::EXAMINATION);
|
||||
$this->setSetting(CcQtiMetadata::QMD_SCORETYPE, CcQtiValues::PERCENTAGE);
|
||||
//optional empty values
|
||||
$this->setSetting(CcQtiMetadata::QMD_FEEDBACKPERMITTED);
|
||||
$this->setSetting(CcQtiMetadata::QMD_HINTSPERMITTED);
|
||||
$this->setSetting(CcQtiMetadata::QMD_SOLUTIONSPERMITTED);
|
||||
$this->setSetting(CcQtiMetadata::QMD_TIMELIMIT);
|
||||
$this->setSetting(CcQtiMetadata::CC_ALLOW_LATE_SUBMISSION);
|
||||
$this->setSetting(CcQtiMetadata::CC_MAXATTEMPTS);
|
||||
}
|
||||
|
||||
public function enableHints($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiMetadata::QMD_HINTSPERMITTED, $value);
|
||||
}
|
||||
|
||||
public function enableSolutions($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiMetadata::QMD_SOLUTIONSPERMITTED, $value);
|
||||
}
|
||||
|
||||
public function enableLatesubmissions($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiMetadata::CC_ALLOW_LATE_SUBMISSION, $value);
|
||||
}
|
||||
|
||||
public function enableFeedback($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiMetadata::QMD_FEEDBACKPERMITTED, $value);
|
||||
}
|
||||
|
||||
public function setTimelimit($value)
|
||||
{
|
||||
$ivalue = (int) $value;
|
||||
if (($ivalue < 0) || ($ivalue > 527401)) {
|
||||
throw new OutOfRangeException('Time limit value out of permitted range!');
|
||||
}
|
||||
|
||||
$this->setSetting(CcQtiMetadata::QMD_TIMELIMIT, $value);
|
||||
}
|
||||
|
||||
public function setMaxattempts($value)
|
||||
{
|
||||
$valid_values = [CcQtiValues::EXAMINATION, CcQtiValues::UNLIMITED, 1, 2, 3, 4, 5];
|
||||
if (!in_array($value, $valid_values)) {
|
||||
throw new OutOfRangeException('Max attempts has invalid value');
|
||||
}
|
||||
|
||||
$this->setSetting(CcQtiMetadata::CC_MAXATTEMPTS, $value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentPresentation extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $flow = null;
|
||||
protected $material = null;
|
||||
protected $responseLid = null;
|
||||
protected $responseStr = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::LABEL);
|
||||
$this->setSettingWns(CcQtiTags::XML_LANG, CcXmlNamespace::XML);
|
||||
$this->setSetting(CcQtiTags::X0);
|
||||
$this->setSetting(CcQtiTags::Y0);
|
||||
$this->setSetting(CcQtiTags::WIDTH);
|
||||
$this->setSetting(CcQtiTags::HEIGHT);
|
||||
}
|
||||
|
||||
public function setLabel($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::LABEL, $value);
|
||||
}
|
||||
|
||||
public function setLang($value)
|
||||
{
|
||||
$this->setSettingWns(CcQtiTags::XML_LANG, CcXmlNamespace::XML, $value);
|
||||
}
|
||||
|
||||
public function setCoor($x = null, $y = null)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::X0, $x);
|
||||
$this->setSetting(CcQtiTags::Y0, $y);
|
||||
}
|
||||
|
||||
public function setSize($width = null, $height = null)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::WIDTH, $width);
|
||||
$this->setSetting(CcQtiTags::HEIGHT, $height);
|
||||
}
|
||||
|
||||
public function setFlow(CcAssesmentFlowtype $object)
|
||||
{
|
||||
$this->flow = $object;
|
||||
}
|
||||
|
||||
public function setMaterial(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->material = $object;
|
||||
}
|
||||
|
||||
public function setResponseLid(CcResponseLidtype $object)
|
||||
{
|
||||
$this->responseLid = $object;
|
||||
}
|
||||
|
||||
public function setResponseStr(CcAssesmentResponseStrtype $object)
|
||||
{
|
||||
$this->responseStr = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::PRESENTATION);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->flow)) {
|
||||
$this->flow->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->material) && empty($this->flow)) {
|
||||
$this->material->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->responseLid) && empty($this->flow)) {
|
||||
$this->responseLid->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->responseStr) && empty($this->flow)) {
|
||||
$this->responseStr->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentPresentationMaterialBase extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $flowmats = [];
|
||||
|
||||
public function addFlowMat($object)
|
||||
{
|
||||
$this->flowmats[] = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::PRESENTATION_MATERIAL);
|
||||
if (!empty($this->flowmats)) {
|
||||
foreach ($this->flowmats as $flowMat) {
|
||||
$flowMat->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentQuestionEssay extends CcAssesmentQuestionProcBase
|
||||
{
|
||||
public function __construct($quiz, $questions, $manifest, $section, $question, $rootpath, $contextid, $outdir)
|
||||
{
|
||||
parent::__construct($quiz, $questions, $manifest, $section, $question, $rootpath, $contextid, $outdir);
|
||||
$this->qtype = CcQtiProfiletype::ESSAY;
|
||||
|
||||
$questionScore = $question->ponderation;
|
||||
/*
|
||||
// Looks useless for CC13!?
|
||||
if (is_int($questionScore)) {
|
||||
$questionScore = ($questionScore).'.0000000';
|
||||
}
|
||||
*/
|
||||
$this->total_grade_value = $questionScore;
|
||||
$this->totalGradeValue = $questionScore;
|
||||
$this->qitem->setTitle($question->question);
|
||||
}
|
||||
|
||||
public function onGenerateAnswers()
|
||||
{
|
||||
//add responses holder
|
||||
$answerlist = [];
|
||||
$this->answerlist = $answerlist;
|
||||
}
|
||||
|
||||
public function onGenerateFeedbacks()
|
||||
{
|
||||
parent::onGenerateFeedbacks();
|
||||
}
|
||||
|
||||
public function onGenerateResponseProcessing()
|
||||
{
|
||||
parent::onGenerateResponseProcessing();
|
||||
|
||||
/**
|
||||
* General unconditional feedback must be added as a first respcondition
|
||||
* without any condition and just displayfeedback (if exists).
|
||||
*/
|
||||
$qrespcondition = new CcAssesmentRespconditiontype();
|
||||
$qrespcondition->setTitle('General feedback');
|
||||
$this->qresprocessing->addRespcondition($qrespcondition);
|
||||
$qrespcondition->enableContinue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentQuestionFib extends CcAssesmentQuestionProcBase
|
||||
{
|
||||
public function __construct($quiz, $questions, $manifest, $section, $questionNode, $rootpath, $contextid, $outdir)
|
||||
{
|
||||
parent::__construct($quiz, $questions, $manifest, $section, $questionNode, $rootpath, $contextid, $outdir);
|
||||
$this->qtype = CcQtiProfiletype::FIELD_ENTRY;
|
||||
$correctAnswerNodes = [];
|
||||
$questionScore = 0;
|
||||
foreach ($questionNode->answers as $index => $answer) {
|
||||
$answerScore = 0;
|
||||
$answerText = $answer['answer'];
|
||||
$pos = strrpos($answerText, '::');
|
||||
list($answerText, $answerRules) = explode('::', $answerText);
|
||||
$matches = [];
|
||||
list($weights, $sizes, $others) = explode(':', $answerRules);
|
||||
$weights = explode(',', $weights);
|
||||
$i = 0;
|
||||
// Todo: improve to tolerate all separators
|
||||
if (preg_match_all('/\[(.*?)\]/', $answerText, $matches)) {
|
||||
foreach ($matches[1] as $match) {
|
||||
$correctAnswerNodes[] = $match;
|
||||
$questionScore += $weights[$i];
|
||||
$answerScore += $weights[$i];
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
$questionNode->answers[$index] = [
|
||||
'answer' => $answerText,
|
||||
'ponderation' => $answerScore,
|
||||
'comment' => $answer['comment'],
|
||||
];
|
||||
$questionScore++;
|
||||
}
|
||||
if (count($correctAnswerNodes) == 0) {
|
||||
throw new RuntimeException('No correct answer!');
|
||||
}
|
||||
$this->correctAnswers = $correctAnswerNodes;
|
||||
$this->totalGradeValue = $questionScore;
|
||||
}
|
||||
|
||||
public function onGenerateAnswers()
|
||||
{
|
||||
//add responses holder
|
||||
$qresponseLid = new CcResponseLidtype();
|
||||
$this->qresponseLid = $qresponseLid;
|
||||
$this->qpresentation->setResponseLid($qresponseLid);
|
||||
$qresponseChoice = new CcAssesmentRenderFibtype();
|
||||
$qresponseLid->setRenderFib($qresponseChoice);
|
||||
|
||||
//Mark that question has more than one correct answer
|
||||
$qresponseLid->setRcardinality(CcQtiValues::MULTIPLE);
|
||||
|
||||
//are we to shuffle the responses?
|
||||
$shuffleAnswers = $this->quiz['random_answers'] > 0;
|
||||
|
||||
$qresponseChoice->enableShuffle($shuffleAnswers);
|
||||
$answerlist = [];
|
||||
|
||||
$qaResponses = $this->questionNode->answers;
|
||||
|
||||
foreach ($qaResponses as $node) {
|
||||
$answerContent = $node['answer'];
|
||||
$answerGradeFraction = $node['ponderation'];
|
||||
|
||||
$result = CcHelpers::processLinkedFiles($answerContent,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
|
||||
$qresponseLabel = CcAssesmentHelper::addAnswer($qresponseChoice,
|
||||
$result[0],
|
||||
CcQtiValues::HTMLTYPE);
|
||||
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
|
||||
$answerIdent = $qresponseLabel->getIdent();
|
||||
$feedbackIdent = $answerIdent.'_fb';
|
||||
//add answer specific feedbacks if not empty
|
||||
$content = $node['comment'];
|
||||
if (!empty($content)) {
|
||||
$result = CcHelpers::processLinkedFiles($content,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
|
||||
CcAssesmentHelper::addFeedback($this->qitem,
|
||||
$result[0],
|
||||
CcQtiValues::HTMLTYPE,
|
||||
$feedbackIdent);
|
||||
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
}
|
||||
$answerlist[$answerIdent] = [$feedbackIdent, ($answerGradeFraction > 0)];
|
||||
}
|
||||
$this->answerlist = $answerlist;
|
||||
}
|
||||
|
||||
public function onGenerateFeedbacks()
|
||||
{
|
||||
parent::onGenerateFeedbacks();
|
||||
}
|
||||
|
||||
public function onGenerateResponseProcessing()
|
||||
{
|
||||
parent::onGenerateResponseProcessing();
|
||||
|
||||
/**
|
||||
* General unconditional feedback must be added as a first respcondition
|
||||
* without any condition and just displayfeedback (if exists).
|
||||
*/
|
||||
$qrespcondition = new CcAssesmentRespconditiontype();
|
||||
$qrespcondition->setTitle('General feedback');
|
||||
$this->qresprocessing->addRespcondition($qrespcondition);
|
||||
$qrespcondition->enableContinue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentQuestionMultichoice extends CcAssesmentQuestionProcBase
|
||||
{
|
||||
public function __construct($quiz, $questions, $manifest, $section, $question, $rootpath, $contextid, $outdir)
|
||||
{
|
||||
parent::__construct($quiz, $questions, $manifest, $section, $question, $rootpath, $contextid, $outdir);
|
||||
$this->qtype = CcQtiProfiletype::MULTIPLE_CHOICE;
|
||||
|
||||
$correctAnswerNode = 0;
|
||||
$questionScore = 0;
|
||||
foreach ($question->answers as $answer) {
|
||||
if ($answer['correct'] > 0) {
|
||||
$correctAnswerNode = 1;
|
||||
$this->correctAnswerNodeId = $answer['id'];
|
||||
$questionScore = $answer['ponderation'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (empty($correctAnswerNode)) {
|
||||
throw new RuntimeException('No correct answer!');
|
||||
}
|
||||
//$this->total_grade_value = ($question_score).'.0000000';
|
||||
$this->totalGradeValue = $questionScore;
|
||||
}
|
||||
|
||||
public function onGenerateAnswers()
|
||||
{
|
||||
//add responses holder
|
||||
$qresponseLid = new CcResponseLidtype();
|
||||
$this->qresponseLid = $qresponseLid;
|
||||
$this->qpresentation->setResponseLid($qresponseLid);
|
||||
$qresponseChoice = new CcAssesmentRenderChoicetype();
|
||||
$qresponseLid->setRenderChoice($qresponseChoice);
|
||||
|
||||
//Mark that question has only one correct answer -
|
||||
//which applies for multiple choice and yes/no questions
|
||||
$qresponseLid->setRcardinality(CcQtiValues::SINGLE);
|
||||
|
||||
//are we to shuffle the responses?
|
||||
$shuffleAnswers = $this->quiz['random_answers'] > 0;
|
||||
|
||||
$qresponseChoice->enableShuffle($shuffleAnswers);
|
||||
$answerlist = [];
|
||||
|
||||
$qaResponses = $this->questionNode->answers;
|
||||
|
||||
foreach ($qaResponses as $node) {
|
||||
$answerContent = $node['answer'];
|
||||
$id = $node['id'];
|
||||
|
||||
$result = CcHelpers::processLinkedFiles($answerContent,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
|
||||
$qresponseLabel = CcAssesmentHelper::addAnswer($qresponseChoice,
|
||||
$result[0],
|
||||
CcQtiValues::HTMLTYPE);
|
||||
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
|
||||
$answerIdent = $qresponseLabel->getIdent();
|
||||
$feedbackIdent = $answerIdent.'_fb';
|
||||
if (empty($this->correctAnswerIdent) && $id && $this->correctAnswerNodeId == $id) {
|
||||
$this->correctAnswerIdent = $answerIdent;
|
||||
}
|
||||
|
||||
//add answer specific feedbacks if not empty
|
||||
$content = $node['comment'];
|
||||
|
||||
if (empty($content)) {
|
||||
$content = '';
|
||||
}
|
||||
$result = CcHelpers::processLinkedFiles($content,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
|
||||
CcAssesmentHelper::addFeedback($this->qitem,
|
||||
$result[0],
|
||||
CcQtiValues::HTMLTYPE,
|
||||
$feedbackIdent);
|
||||
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
$answerlist[$answerIdent] = $feedbackIdent;
|
||||
}
|
||||
$this->answerlist = $answerlist;
|
||||
}
|
||||
|
||||
public function onGenerateFeedbacks()
|
||||
{
|
||||
parent::onGenerateFeedbacks();
|
||||
|
||||
//Question combined feedbacks
|
||||
$correctQuestionFb = '';
|
||||
$incorrectQuestionFb = '';
|
||||
|
||||
if (empty($correctQuestionFb)) {
|
||||
//Hardcode some text for now
|
||||
$correctQuestionFb = 'Well done!';
|
||||
}
|
||||
if (empty($incorrectQuestionFb)) {
|
||||
//Hardcode some text for now
|
||||
$incorrectQuestionFb = 'Better luck next time!';
|
||||
}
|
||||
|
||||
$proc = ['correct_fb' => $correctQuestionFb, 'general_incorrect_fb' => $incorrectQuestionFb];
|
||||
foreach ($proc as $ident => $content) {
|
||||
if (empty($content)) {
|
||||
continue;
|
||||
}
|
||||
$result = CcHelpers::processLinkedFiles($content,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
CcAssesmentHelper::addFeedback($this->qitem,
|
||||
$result[0],
|
||||
CcQtiValues::HTMLTYPE,
|
||||
$ident);
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
if ($ident == 'correct_fb') {
|
||||
$this->correctFeedbacks[] = $ident;
|
||||
} else {
|
||||
$this->incorrectFeedbacks[] = $ident;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function onGenerateResponseProcessing()
|
||||
{
|
||||
parent::onGenerateResponseProcessing();
|
||||
|
||||
//respconditions
|
||||
/**
|
||||
* General unconditional feedback must be added as a first respcondition
|
||||
* without any condition and just displayfeedback (if exists).
|
||||
*/
|
||||
if (!empty($this->generalFeedback)) {
|
||||
$qrespcondition = new CcAssesmentRespconditiontype();
|
||||
$qrespcondition->setTitle('General feedback');
|
||||
$this->qresprocessing->addRespcondition($qrespcondition);
|
||||
$qrespcondition->enableContinue();
|
||||
//define the condition for success
|
||||
$qconditionvar = new CcAssignmentConditionvar();
|
||||
$qrespcondition->setConditionvar($qconditionvar);
|
||||
$qother = new CcAssignmentConditionvarOthertype();
|
||||
$qconditionvar->setOther($qother);
|
||||
$qdisplayfeedback = new CcAssignmentDisplayfeedbacktype();
|
||||
$qrespcondition->addDisplayfeedback($qdisplayfeedback);
|
||||
$qdisplayfeedback->setFeedbacktype(CcQtiValues::RESPONSE);
|
||||
$qdisplayfeedback->setLinkrefid('general_fb');
|
||||
}
|
||||
|
||||
//success condition
|
||||
$qrespcondition = new CcAssesmentRespconditiontype();
|
||||
$qrespcondition->setTitle('Correct');
|
||||
$this->qresprocessing->addRespcondition($qrespcondition);
|
||||
$qrespcondition->enableContinue(false);
|
||||
$qsetvar = new CcAssignmentSetvartype(100);
|
||||
$qrespcondition->addSetvar($qsetvar);
|
||||
//define the condition for success
|
||||
$qconditionvar = new CcAssignmentConditionvar();
|
||||
$qrespcondition->setConditionvar($qconditionvar);
|
||||
$qvarequal = new CcAssignmentConditionvarVarequaltype($this->correctAnswerIdent);
|
||||
$qconditionvar->setVarequal($qvarequal);
|
||||
$qvarequal->setRespident($this->qresponseLid->getIdent());
|
||||
|
||||
if (array_key_exists($this->correctAnswerIdent, $this->answerlist)) {
|
||||
$qdisplayfeedback = new CcAssignmentDisplayfeedbacktype();
|
||||
$qrespcondition->addDisplayfeedback($qdisplayfeedback);
|
||||
$qdisplayfeedback->setFeedbacktype(CcQtiValues::RESPONSE);
|
||||
$qdisplayfeedback->setLinkrefid($this->answerlist[$this->correctAnswerIdent]);
|
||||
}
|
||||
|
||||
foreach ($this->correctFeedbacks as $ident) {
|
||||
$qdisplayfeedback = new CcAssignmentDisplayfeedbacktype();
|
||||
$qrespcondition->addDisplayfeedback($qdisplayfeedback);
|
||||
$qdisplayfeedback->setFeedbacktype(CcQtiValues::RESPONSE);
|
||||
$qdisplayfeedback->setLinkrefid($ident);
|
||||
}
|
||||
|
||||
//rest of the conditions
|
||||
foreach ($this->answerlist as $ident => $refid) {
|
||||
if ($ident == $this->correctAnswerIdent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$qrespcondition = new CcAssesmentRespconditiontype();
|
||||
$this->qresprocessing->addRespcondition($qrespcondition);
|
||||
$qsetvar = new CcAssignmentSetvartype(0);
|
||||
$qrespcondition->addSetvar($qsetvar);
|
||||
//define the condition for fail
|
||||
$qconditionvar = new CcAssignmentConditionvar();
|
||||
$qrespcondition->setConditionvar($qconditionvar);
|
||||
$qvarequal = new CcAssignmentConditionvarVarequaltype($ident);
|
||||
$qconditionvar->setVarequal($qvarequal);
|
||||
$qvarequal->setRespident($this->qresponseLid->getIdent());
|
||||
|
||||
$qdisplayfeedback = new CcAssignmentDisplayfeedbacktype();
|
||||
$qrespcondition->addDisplayfeedback($qdisplayfeedback);
|
||||
$qdisplayfeedback->setFeedbacktype(CcQtiValues::RESPONSE);
|
||||
$qdisplayfeedback->setLinkrefid($refid);
|
||||
|
||||
foreach ($this->incorrectFeedbacks as $ident) {
|
||||
$qdisplayfeedback = new CcAssignmentDisplayfeedbacktype();
|
||||
$qrespcondition->addDisplayfeedback($qdisplayfeedback);
|
||||
$qdisplayfeedback->setFeedbacktype(CcQtiValues::RESPONSE);
|
||||
$qdisplayfeedback->setLinkrefid($ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentQuestionMultichoiceMultiresponse extends CcAssesmentQuestionProcBase
|
||||
{
|
||||
protected $correctAnswers = null;
|
||||
|
||||
public function __construct($quiz, $questions, $manifest, $section, $questionNode, $rootpath, $contextid, $outdir)
|
||||
{
|
||||
parent::__construct($quiz, $questions, $manifest, $section, $questionNode, $rootpath, $contextid, $outdir);
|
||||
$this->qtype = CcQtiProfiletype::MULTIPLE_RESPONSE;
|
||||
|
||||
$correctAnswerNodes = [];
|
||||
$questionScore = 0;
|
||||
foreach ($questionNode->answers as $answer) {
|
||||
if ($answer['correct'] > 0) {
|
||||
$correctAnswerNodes[] = $answer;
|
||||
$questionScore += $answer['ponderation'];
|
||||
}
|
||||
}
|
||||
if (count($correctAnswerNodes) == 0) {
|
||||
throw new RuntimeException('No correct answer!');
|
||||
}
|
||||
$this->correctAnswers = $correctAnswerNodes;
|
||||
$this->totalGradeValue = $questionScore;
|
||||
}
|
||||
|
||||
public function onGenerateAnswers()
|
||||
{
|
||||
//add responses holder
|
||||
$qresponseLid = new CcResponseLidtype();
|
||||
$this->qresponseLid = $qresponseLid;
|
||||
$this->qpresentation->setResponseLid($qresponseLid);
|
||||
$qresponseChoice = new CcAssesmentRenderChoicetype();
|
||||
$qresponseLid->setRenderChoice($qresponseChoice);
|
||||
//Mark that question has more than one correct answer
|
||||
$qresponseLid->setRcardinality(CcQtiValues::MULTIPLE);
|
||||
//are we to shuffle the responses?
|
||||
|
||||
$shuffleAnswers = $this->quiz['random_answers'] > 0;
|
||||
$qresponseChoice->enableShuffle($shuffleAnswers);
|
||||
$answerlist = [];
|
||||
|
||||
$qaResponses = $this->questionNode->answers;
|
||||
foreach ($qaResponses as $node) {
|
||||
$answerContent = $node['answer'];
|
||||
$answerGradeFraction = $node['ponderation'];
|
||||
|
||||
$result = CcHelpers::processLinkedFiles($answerContent,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
|
||||
$qresponseLabel = CcAssesmentHelper::addAnswer($qresponseChoice,
|
||||
$result[0],
|
||||
CcQtiValues::HTMLTYPE);
|
||||
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
|
||||
$answerIdent = $qresponseLabel->getIdent();
|
||||
$feedbackIdent = $answerIdent.'_fb';
|
||||
//add answer specific feedbacks if not empty
|
||||
$content = $node['comment'];
|
||||
if (!empty($content)) {
|
||||
$result = CcHelpers::processLinkedFiles($content,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
|
||||
CcAssesmentHelper::addFeedback($this->qitem,
|
||||
$result[0],
|
||||
CcQtiValues::HTMLTYPE,
|
||||
$feedbackIdent);
|
||||
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
}
|
||||
$answerlist[$answerIdent] = [$feedbackIdent, ($answerGradeFraction > 0)];
|
||||
}
|
||||
$this->answerlist = $answerlist;
|
||||
}
|
||||
|
||||
public function onGenerateFeedbacks()
|
||||
{
|
||||
parent::onGenerateFeedbacks();
|
||||
//Question combined feedbacks
|
||||
$correctQuestionFb = '';
|
||||
$incorrectQuestionFb = '';
|
||||
if (empty($correctQuestionFb)) {
|
||||
//Hardcode some text for now
|
||||
$correctQuestionFb = 'Well done!';
|
||||
}
|
||||
if (empty($incorrectQuestionFb)) {
|
||||
//Hardcode some text for now
|
||||
$incorrectQuestionFb = 'Better luck next time!';
|
||||
}
|
||||
|
||||
$proc = ['correct_fb' => $correctQuestionFb, 'incorrect_fb' => $incorrectQuestionFb];
|
||||
foreach ($proc as $ident => $content) {
|
||||
if (empty($content)) {
|
||||
continue;
|
||||
}
|
||||
$result = CcHelpers::processLinkedFiles($content,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
|
||||
CcAssesmentHelper::addFeedback($this->qitem,
|
||||
$result[0],
|
||||
CcQtiValues::HTMLTYPE,
|
||||
$ident);
|
||||
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
if ($ident == 'correct_fb') {
|
||||
$this->correctFeedbacks[$ident] = $ident;
|
||||
} else {
|
||||
$this->incorrectFeedbacks[$ident] = $ident;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function onGenerateResponseProcessing()
|
||||
{
|
||||
parent::onGenerateResponseProcessing();
|
||||
|
||||
//respconditions
|
||||
/**
|
||||
* General unconditional feedback must be added as a first respcondition
|
||||
* without any condition and just displayfeedback (if exists).
|
||||
*/
|
||||
CcAssesmentHelper::addRespcondition($this->qresprocessing,
|
||||
'General feedback',
|
||||
$this->generalFeedback,
|
||||
null,
|
||||
true
|
||||
);
|
||||
|
||||
$qrespcondition = new CcAssesmentRespconditiontype();
|
||||
$qrespcondition->setTitle('Correct');
|
||||
$this->qresprocessing->addRespcondition($qrespcondition);
|
||||
$qrespcondition->enableContinue(false);
|
||||
$qsetvar = new CcAssignmentSetvartype(100);
|
||||
$qrespcondition->addSetvar($qsetvar);
|
||||
//define the condition for success
|
||||
$qconditionvar = new CcAssignmentConditionvar();
|
||||
$qrespcondition->setConditionvar($qconditionvar);
|
||||
//create root and condition
|
||||
$qandcondition = new CcAssignmentConditionvarAndtype();
|
||||
$qconditionvar->setAnd($qandcondition);
|
||||
foreach ($this->answerlist as $ident => $refid) {
|
||||
$qvarequal = new CcAssignmentConditionvarVarequaltype($ident);
|
||||
$qvarequal->enableCase();
|
||||
if ($refid[1]) {
|
||||
$qandcondition->setVarequal($qvarequal);
|
||||
} else {
|
||||
$qandcondition->setNot($qvarequal);
|
||||
}
|
||||
$qvarequal->setRespident($this->qresponseLid->getIdent());
|
||||
}
|
||||
|
||||
$qdisplayfeedback = new CcAssignmentDisplayfeedbacktype();
|
||||
$qrespcondition->addDisplayfeedback($qdisplayfeedback);
|
||||
$qdisplayfeedback->setFeedbacktype(CcQtiValues::RESPONSE);
|
||||
//TODO: this needs to be fixed
|
||||
reset($this->correctFeedbacks);
|
||||
$ident = key($this->correctFeedbacks);
|
||||
$qdisplayfeedback->setLinkrefid($ident);
|
||||
|
||||
//rest of the conditions
|
||||
foreach ($this->answerlist as $ident => $refid) {
|
||||
CcAssesmentHelper::addResponseCondition($this->qresprocessing,
|
||||
'Incorrect feedback',
|
||||
$refid[0],
|
||||
$this->generalFeedback,
|
||||
$this->qresponseLid->getIdent()
|
||||
);
|
||||
}
|
||||
|
||||
//Final element for incorrect feedback
|
||||
reset($this->incorrectFeedbacks);
|
||||
$ident = key($this->incorrectFeedbacks);
|
||||
CcAssesmentHelper::addRespcondition($this->qresprocessing,
|
||||
'Incorrect feedback',
|
||||
$ident,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentQuestionProcBase
|
||||
{
|
||||
protected $quiz = null;
|
||||
protected $questions = null;
|
||||
protected $manifest = null;
|
||||
protected $section = null;
|
||||
protected $questionNode = null;
|
||||
protected $rootpath = null;
|
||||
protected $contextid = null;
|
||||
protected $outdir = null;
|
||||
protected $qtype = null;
|
||||
protected $qmetadata = null;
|
||||
protected $qitem = null;
|
||||
protected $qpresentation = null;
|
||||
protected $qresponseLid = null;
|
||||
protected $qresprocessing = null;
|
||||
protected $correct_grade_value = null;
|
||||
protected $correctAnswerNodeId = null;
|
||||
protected $correctAnswerIdent = null;
|
||||
protected $totalGradeValue = null;
|
||||
protected $answerlist = null;
|
||||
protected $generalFeedback = null;
|
||||
protected $correctFeedbacks = [];
|
||||
protected $incorrectFeedbacks = [];
|
||||
|
||||
/**
|
||||
* @param XMLGenericDocument $questions
|
||||
* @param cc_assesment_section $section
|
||||
* @param object $question_node
|
||||
* @param string $rootpath
|
||||
* @param string $contextid
|
||||
* @param string $outdir
|
||||
*/
|
||||
public function __construct(&$quiz, &$questions, CcManifest &$manifest, CcAssesmentSection &$section, &$questionNode, $rootpath, $contextid, $outdir)
|
||||
{
|
||||
$this->quiz = $quiz;
|
||||
$this->questions = $questions;
|
||||
$this->manifest = $manifest;
|
||||
$this->section = $section;
|
||||
$this->questionNode = $questionNode;
|
||||
$this->rootpath = $rootpath;
|
||||
$this->contextid = $contextid;
|
||||
$this->outdir = $outdir;
|
||||
$qitem = new CcAssesmentSectionItem();
|
||||
$this->section->addItem($qitem);
|
||||
$qitem->setTitle($questionNode->question);
|
||||
$this->qitem = $qitem;
|
||||
}
|
||||
|
||||
public function onGenerateMetadata()
|
||||
{
|
||||
if (empty($this->qmetadata)) {
|
||||
$this->qmetadata = new CcQuestionMetadata($this->qtype);
|
||||
//Get weighting value
|
||||
$weightingValue = $this->questionNode->ponderation;
|
||||
|
||||
if ($weightingValue > 1) {
|
||||
$this->qmetadata->setWeighting($weightingValue);
|
||||
}
|
||||
|
||||
//Get category
|
||||
if (!empty($this->questionNode->questionCategory)) {
|
||||
$this->qmetadata->setCategory($this->questionNode->questionCategory);
|
||||
}
|
||||
$rts = new CcAssesmentItemmetadata();
|
||||
$rts->addMetadata($this->qmetadata);
|
||||
$this->qitem->setItemmetadata($rts);
|
||||
}
|
||||
}
|
||||
|
||||
public function onGeneratePresentation()
|
||||
{
|
||||
if (empty($this->qpresentation)) {
|
||||
$qpresentation = new CcAssesmentPresentation();
|
||||
$this->qitem->setPresentation($qpresentation);
|
||||
//add question text
|
||||
$qmaterial = new CcAssesmentMaterial();
|
||||
$qmattext = new CcAssesmentMattext();
|
||||
|
||||
$questionText = $this->questionNode->question.'<br>'.$this->questionNode->description;
|
||||
$result = CcHelpers::processLinkedFiles($questionText,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
|
||||
$qmattext->setContent($result[0], CcQtiValues::HTMLTYPE);
|
||||
$qmaterial->setMattext($qmattext);
|
||||
$qpresentation->setMaterial($qmaterial);
|
||||
$this->qpresentation = $qpresentation;
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
}
|
||||
}
|
||||
|
||||
public function onGenerateAnswers()
|
||||
{
|
||||
}
|
||||
|
||||
public function onGenerateFeedbacks()
|
||||
{
|
||||
$generalQuestionFeedback = '';
|
||||
|
||||
if (empty($generalQuestionFeedback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$name = 'general_fb';
|
||||
//Add question general feedback - the one that should be always displayed
|
||||
$result = CcHelpers::processLinkedFiles($generalQuestionFeedback,
|
||||
$this->manifest,
|
||||
$this->rootpath,
|
||||
$this->contextid,
|
||||
$this->outdir);
|
||||
|
||||
CcAssesmentHelper::addFeedback($this->qitem,
|
||||
$result[0],
|
||||
CcQtiValues::HTMLTYPE,
|
||||
$name);
|
||||
|
||||
PkgResourceDependencies::instance()->add($result[1]);
|
||||
$this->generalFeedback = $name;
|
||||
}
|
||||
|
||||
public function onGenerateResponseProcessing()
|
||||
{
|
||||
$qresprocessing = new CcAssesmentResprocessingtype();
|
||||
$this->qitem->addResprocessing($qresprocessing);
|
||||
$qdecvar = new CcAssesmentDecvartype();
|
||||
$qresprocessing->setDecvar($qdecvar);
|
||||
//according to the Common Cartridge 1.1 Profile: Implementation document
|
||||
//this should always be set to 0, 100 in case of question type that is not essay
|
||||
$qdecvar->setLimits(0, 100);
|
||||
$qdecvar->setVartype(CcQtiValues::DECIMAL);
|
||||
|
||||
$this->qresprocessing = $qresprocessing;
|
||||
}
|
||||
|
||||
public function generate()
|
||||
{
|
||||
$this->onGenerateMetadata();
|
||||
|
||||
$this->onGeneratePresentation();
|
||||
|
||||
$this->onGenerateAnswers();
|
||||
|
||||
$this->onGenerateFeedbacks();
|
||||
|
||||
$this->onGenerateResponseProcessing();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentRenderChoicetype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $materials = [];
|
||||
protected $material_refs = [];
|
||||
protected $responseLabels = [];
|
||||
protected $flow_labels = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::SHUFFLE, CcQtiValues::NO);
|
||||
$this->setSetting(CcQtiTags::MINNUMBER);
|
||||
$this->setSetting(CcQtiTags::MAXNUMBER);
|
||||
}
|
||||
|
||||
public function add_material(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->materials[] = $object;
|
||||
}
|
||||
|
||||
public function add_material_ref(CcAssesmentResponseMatref $object)
|
||||
{
|
||||
$this->material_refs[] = $object;
|
||||
}
|
||||
|
||||
public function addResponseLabel(CcAssesmentResponseLabeltype $object)
|
||||
{
|
||||
$this->responseLabels[] = $object;
|
||||
}
|
||||
|
||||
public function add_flow_label($object)
|
||||
{
|
||||
$this->flow_labels[] = $object;
|
||||
}
|
||||
|
||||
public function enableShuffle($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiTags::SHUFFLE, $value);
|
||||
}
|
||||
|
||||
public function setLimits($min = null, $max = null)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::MINNUMBER, $min);
|
||||
$this->setSetting(CcQtiTags::MAXNUMBER, $max);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::RENDER_CHOICE);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->materials)) {
|
||||
foreach ($this->materials as $mattag) {
|
||||
$mattag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->material_refs)) {
|
||||
foreach ($this->material_refs as $matreftag) {
|
||||
$matreftag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->responseLabels)) {
|
||||
foreach ($this->responseLabels as $resplabtag) {
|
||||
$resplabtag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->flow_labels)) {
|
||||
foreach ($this->flow_labels as $flowlabtag) {
|
||||
$flowlabtag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentRenderEssaytype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $materials = [];
|
||||
protected $material_refs = [];
|
||||
protected $responseLabels = [];
|
||||
protected $flow_labels = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::SHUFFLE, CcQtiValues::NO);
|
||||
}
|
||||
|
||||
public function add_material(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->materials[] = $object;
|
||||
}
|
||||
|
||||
public function add_material_ref(CcAssesmentResponseMatref $object)
|
||||
{
|
||||
$this->material_refs[] = $object;
|
||||
}
|
||||
|
||||
public function addResponseLabel(CcAssesmentResponseLabeltype $object)
|
||||
{
|
||||
$this->responseLabels[] = $object;
|
||||
}
|
||||
|
||||
public function add_flow_label($object)
|
||||
{
|
||||
$this->flow_labels[] = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::RENDER_CHOICE);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->materials)) {
|
||||
foreach ($this->materials as $mattag) {
|
||||
$mattag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->material_refs)) {
|
||||
foreach ($this->material_refs as $matreftag) {
|
||||
$matreftag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->responseLabels)) {
|
||||
foreach ($this->responseLabels as $resplabtag) {
|
||||
$resplabtag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->flow_labels)) {
|
||||
foreach ($this->flow_labels as $flowlabtag) {
|
||||
$flowlabtag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentRenderFibtype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $materials = [];
|
||||
protected $material_refs = [];
|
||||
protected $responseLabels = [];
|
||||
protected $flow_labels = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::ENCODING);
|
||||
$this->setSetting(CcQtiTags::CHARSET);
|
||||
$this->setSetting(CcQtiTags::ROWS);
|
||||
$this->setSetting(CcQtiTags::COLUMNS);
|
||||
$this->setSetting(CcQtiTags::MAXCHARS);
|
||||
$this->setSetting(CcQtiTags::MINNUMBER);
|
||||
$this->setSetting(CcQtiTags::MAXNUMBER);
|
||||
$this->setSetting(CcQtiTags::PROMPT, CcQtiValues::BOX);
|
||||
$this->setSetting(CcQtiTags::FIBTYPE, CcQtiValues::STRING);
|
||||
$this->qtype = CcQtiProfiletype::FIELD_ENTRY;
|
||||
}
|
||||
|
||||
public function add_material(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->materials[] = $object;
|
||||
}
|
||||
|
||||
public function add_material_ref(CcAssesmentResponseMatref $object)
|
||||
{
|
||||
$this->material_refs[] = $object;
|
||||
}
|
||||
|
||||
public function addResponseLabel(CcAssesmentResponseLabeltype $object)
|
||||
{
|
||||
$this->responseLabels[] = $object;
|
||||
}
|
||||
|
||||
public function add_flow_label($object)
|
||||
{
|
||||
$this->flow_labels[] = $object;
|
||||
}
|
||||
|
||||
public function enableShuffle($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiTags::SHUFFLE, $value);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::RENDER_FIB);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->materials)) {
|
||||
foreach ($this->materials as $mattag) {
|
||||
$mattag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->material_refs)) {
|
||||
foreach ($this->material_refs as $matreftag) {
|
||||
$matreftag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->responseLabels)) {
|
||||
foreach ($this->responseLabels as $resplabtag) {
|
||||
$resplabtag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->flow_labels)) {
|
||||
foreach ($this->flow_labels as $flowlabtag) {
|
||||
$flowlabtag->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentRespconditiontype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $conditionvar = null;
|
||||
protected $setvar = [];
|
||||
protected $displayfeedback = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::TITLE);
|
||||
$this->setSetting(CcQtiTags::CONTINUE_, CcQtiValues::NO);
|
||||
}
|
||||
|
||||
public function setTitle($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::TITLE, $value);
|
||||
}
|
||||
|
||||
public function enableContinue($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiTags::CONTINUE_, $value);
|
||||
}
|
||||
|
||||
public function setConditionvar(CcAssignmentConditionvar $object)
|
||||
{
|
||||
$this->conditionvar = $object;
|
||||
}
|
||||
|
||||
public function addSetvar(CcAssignmentSetvartype $object)
|
||||
{
|
||||
$this->setvar[] = $object;
|
||||
}
|
||||
|
||||
public function addDisplayfeedback(CcAssignmentDisplayfeedbacktype $object)
|
||||
{
|
||||
$this->displayfeedback[] = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::RESPCONDITION);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->conditionvar)) {
|
||||
$this->conditionvar->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->setvar)) {
|
||||
foreach ($this->setvar as $setvar) {
|
||||
$setvar->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->displayfeedback)) {
|
||||
foreach ($this->displayfeedback as $displayfeedback) {
|
||||
$displayfeedback->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentResponseLabeltype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $material = null;
|
||||
protected $materialRef = null;
|
||||
protected $flowMat = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::IDENT, CcHelpers::uuidgen('I_'));
|
||||
$this->setSetting(CcQtiTags::LABELREFID);
|
||||
$this->setSetting(CcQtiTags::RSHUFFLE);
|
||||
$this->setSetting(CcQtiTags::MATCH_GROUP);
|
||||
$this->setSetting(CcQtiTags::MATCH_MAX);
|
||||
}
|
||||
|
||||
public function setIdent($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::IDENT, $value);
|
||||
}
|
||||
|
||||
public function getIdent()
|
||||
{
|
||||
return $this->getSetting(CcQtiTags::IDENT);
|
||||
}
|
||||
|
||||
public function setLabelrefid($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::LABELREFID, $value);
|
||||
}
|
||||
|
||||
public function enableRshuffle($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiTags::RSHUFFLE, $value);
|
||||
}
|
||||
|
||||
public function setMatchGroup($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::MATCH_GROUP, $value);
|
||||
}
|
||||
|
||||
public function setMatchMax($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::MATCH_MAX, $value);
|
||||
}
|
||||
|
||||
public function setMaterial(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->material = $object;
|
||||
}
|
||||
|
||||
public function setMaterialRef(CcAssesmentResponseMatref $object)
|
||||
{
|
||||
$this->materialRef = $object;
|
||||
}
|
||||
|
||||
public function setFlowMat(CcAssesmentFlowMattype $object)
|
||||
{
|
||||
$this->flowMat = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::RESPONSE_LABEL);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->material)) {
|
||||
$this->material->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->materialRef)) {
|
||||
$this->materialRef->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->flowMat)) {
|
||||
$this->flowMat->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentResponseMatref extends CcAssesmentMatref
|
||||
{
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::MATERIAL_REF);
|
||||
$doc->appendNewAttributeNs($node, $namespace, CcQtiTags::LINKREFID, $this->linkref);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentResponseStrtype extends CcResponseLidtype
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$rtt = parent::__construct();
|
||||
$this->tagname = CcQtiTags::RESPONSE_STR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentResprocessingtype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $decvar = null;
|
||||
protected $respconditions = [];
|
||||
|
||||
public function setDecvar(CcAssesmentDecvartype $object)
|
||||
{
|
||||
$this->decvar = $object;
|
||||
}
|
||||
|
||||
public function addRespcondition(CcAssesmentRespconditiontype $object)
|
||||
{
|
||||
$this->respconditions[] = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::RESPROCESSING);
|
||||
$outcomes = $doc->appendNewElementNs($node, $namespace, CcQtiTags::OUTCOMES);
|
||||
if (!empty($this->decvar)) {
|
||||
$this->decvar->generate($doc, $outcomes, $namespace);
|
||||
}
|
||||
if (!empty($this->respconditions)) {
|
||||
foreach ($this->respconditions as $rcond) {
|
||||
$rcond->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentRubricBase extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $material = null;
|
||||
|
||||
public function setMaterial($object)
|
||||
{
|
||||
$this->material = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$rubric = $doc->appendNewElementNs($item, $namespace, CcQtiTags::RUBRIC);
|
||||
if (!empty($this->material)) {
|
||||
$this->material->generate($doc, $rubric, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentSection extends CcQuestionMetadataBase
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $items = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::IDENT, CcHelpers::uuidgen('I_'));
|
||||
$this->setSetting(CcQtiTags::TITLE);
|
||||
$this->setSettingWns(CcQtiTags::XML_LANG, CcXmlNamespace::XML);
|
||||
}
|
||||
|
||||
public function setIdent($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::IDENT, $value);
|
||||
}
|
||||
|
||||
public function setTitle($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::TITLE, $value);
|
||||
}
|
||||
|
||||
public function setLang($value)
|
||||
{
|
||||
$this->setSettingWns(CcQtiTags::XML_LANG, CcXmlNamespace::XML, $value);
|
||||
}
|
||||
|
||||
public function addItem(CcAssesmentSectionItem $object)
|
||||
{
|
||||
$this->items[] = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::SECTION);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
if (!empty($this->items)) {
|
||||
foreach ($this->items as $item) {
|
||||
$item->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssesmentSectionItem extends CcAssesmentSection
|
||||
{
|
||||
protected $itemmetadata = null;
|
||||
protected $presentation = null;
|
||||
protected $resprocessing = [];
|
||||
protected $itemfeedback = [];
|
||||
|
||||
public function setItemmetadata(CcAssesmentItemmetadata $object)
|
||||
{
|
||||
$this->itemmetadata = $object;
|
||||
}
|
||||
|
||||
public function setPresentation(CcAssesmentPresentation $object)
|
||||
{
|
||||
$this->presentation = $object;
|
||||
}
|
||||
|
||||
public function addResprocessing(CcAssesmentResprocessingtype $object)
|
||||
{
|
||||
$this->resprocessing[] = $object;
|
||||
}
|
||||
|
||||
public function addItemfeedback(CcAssesmentItemfeedbacktype $object)
|
||||
{
|
||||
$this->itemfeedback[] = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::ITEM);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->itemmetadata)) {
|
||||
$this->itemmetadata->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->presentation)) {
|
||||
$this->presentation->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->resprocessing)) {
|
||||
foreach ($this->resprocessing as $resprocessing) {
|
||||
$resprocessing->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->itemfeedback)) {
|
||||
foreach ($this->itemfeedback as $itemfeedback) {
|
||||
$itemfeedback->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssignmentConditionvar extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $and = null;
|
||||
protected $other = null;
|
||||
protected $varequal = [];
|
||||
protected $varsubstring = null;
|
||||
|
||||
public function setAnd(CcAssignmentConditionvarAndtype $object)
|
||||
{
|
||||
$this->and = $object;
|
||||
}
|
||||
|
||||
public function setOther(CcAssignmentConditionvarOthertype $object)
|
||||
{
|
||||
$this->other = $object;
|
||||
}
|
||||
|
||||
public function setVarequal(CcAssignmentConditionvarVarequaltype $object)
|
||||
{
|
||||
$this->varequal[] = $object;
|
||||
}
|
||||
|
||||
public function setVarsubstring(CcAssignmentConditionvarVarsubstringtype $object)
|
||||
{
|
||||
$this->varsubstring = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::CONDITIONVAR);
|
||||
|
||||
if (!empty($this->and)) {
|
||||
$this->and->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->other)) {
|
||||
$this->other->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->varequal)) {
|
||||
foreach ($this->varequal as $varequal) {
|
||||
$varequal->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->varsubstring)) {
|
||||
$this->varsubstring->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssignmentConditionvarAndtype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $nots = [];
|
||||
protected $varequals = [];
|
||||
|
||||
public function setNot(CcAssignmentConditionvarVarequaltype $object)
|
||||
{
|
||||
$this->nots[] = $object;
|
||||
}
|
||||
|
||||
public function setVarequal(CcAssignmentConditionvarVarequaltype $object)
|
||||
{
|
||||
$this->varequals[] = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::AND_);
|
||||
if (!empty($this->nots)) {
|
||||
foreach ($this->nots as $notv) {
|
||||
$not = $doc->appendNewElementNs($node, $namespace, CcQtiTags::NOT_);
|
||||
$notv->generate($doc, $not, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->varequals)) {
|
||||
foreach ($this->varequals as $varequal) {
|
||||
$varequal->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssignmentConditionvarOthertype extends CcQuestionMetadataBase
|
||||
{
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$doc->appendNewElementNs($item, $namespace, CcQtiTags::OTHER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssignmentConditionvarVarequaltype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $tagname = null;
|
||||
protected $answerid = null;
|
||||
|
||||
public function __construct($value = null)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
throw new InvalidArgumentException('Must not pass null!');
|
||||
}
|
||||
$this->answerid = $value;
|
||||
$this->setSetting(CcQtiTags::RESPIDENT);
|
||||
$this->setSetting(CcQtiTags::CASE_);
|
||||
$this->tagname = CcQtiTags::VAREQUAL;
|
||||
}
|
||||
|
||||
public function setRespident($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::RESPIDENT, $value);
|
||||
}
|
||||
|
||||
public function enableCase($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiTags::CASE_, $value);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, $this->tagname, $this->answerid);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssignmentConditionvarVarsubstringtype extends CcAssignmentConditionvarVarequaltype
|
||||
{
|
||||
public function __construct($value)
|
||||
{
|
||||
parent::__construct($value);
|
||||
$this->tagname = CcQtiTags::VARSUBSTRING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssignmentDisplayfeedbacktype extends CcQuestionMetadataBase
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::FEEDBACKTYPE);
|
||||
$this->setSetting(CcQtiTags::LINKREFID);
|
||||
}
|
||||
|
||||
public function setFeedbacktype($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::FEEDBACKTYPE, $value);
|
||||
}
|
||||
|
||||
public function setLinkrefid($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::LINKREFID, $value);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::DISPLAYFEEDBACK);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcAssignmentSetvartype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $tagvalue = null;
|
||||
|
||||
public function __construct($tagvalue = 100)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::VARNAME, CcQtiValues::SCORE);
|
||||
$this->setSetting(CcQtiTags::ACTION, CcQtiValues::SET);
|
||||
$this->tagvalue = $tagvalue;
|
||||
}
|
||||
|
||||
public function setVarname($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::VARNAME, $value);
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::SETVAR, $this->tagvalue);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
abstract class CcQtiMetadata
|
||||
{
|
||||
// Assessment.
|
||||
public const QMD_ASSESSMENTTYPE = 'qmd_assessmenttype';
|
||||
public const QMD_SCORETYPE = 'qmd_scoretype';
|
||||
public const QMD_FEEDBACKPERMITTED = 'qmd_feedbackpermitted';
|
||||
public const QMD_HINTSPERMITTED = 'qmd_hintspermitted';
|
||||
public const QMD_SOLUTIONSPERMITTED = 'qmd_solutionspermitted';
|
||||
public const QMD_TIMELIMIT = 'qmd_timelimit';
|
||||
public const CC_ALLOW_LATE_SUBMISSION = 'cc_allow_late_submission';
|
||||
public const CC_MAXATTEMPTS = 'cc_maxattempts';
|
||||
public const CC_PROFILE = 'cc_profile';
|
||||
|
||||
// Items.
|
||||
public const CC_WEIGHTING = 'cc_weighting';
|
||||
public const QMD_SCORINGPERMITTED = 'qmd_scoringpermitted';
|
||||
public const QMD_COMPUTERSCORED = 'qmd_computerscored';
|
||||
public const CC_QUESTION_CATEGORY = 'cc_question_category';
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
abstract class CcQtiProfiletype
|
||||
{
|
||||
public const MULTIPLE_CHOICE = 'cc.multiple_choice.v0p1';
|
||||
public const MULTIPLE_RESPONSE = 'cc.multiple_response.v0p1';
|
||||
public const TRUE_FALSE = 'cc.true_false.v0p1';
|
||||
public const FIELD_ENTRY = 'cc.fib.v0p1';
|
||||
public const PATTERN_MATCH = 'cc.pattern_match.v0p1';
|
||||
public const ESSAY = 'cc.essay.v0p1';
|
||||
|
||||
/**
|
||||
* validates a profile value.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function valid($value)
|
||||
{
|
||||
static $verificationValues = [
|
||||
self::ESSAY,
|
||||
self::FIELD_ENTRY,
|
||||
self::MULTIPLE_CHOICE,
|
||||
self::MULTIPLE_RESPONSE,
|
||||
self::PATTERN_MATCH,
|
||||
self::TRUE_FALSE,
|
||||
];
|
||||
|
||||
return in_array($value, $verificationValues);
|
||||
}
|
||||
}
|
||||
88
main/common_cartridge/export/src/lib/assesment/CcQtiTags.php
Normal file
88
main/common_cartridge/export/src/lib/assesment/CcQtiTags.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
abstract class CcQtiTags
|
||||
{
|
||||
public const QUESTESTINTEROP = 'questestinterop';
|
||||
public const ASSESSMENT = 'assessment';
|
||||
public const QTIMETADATA = 'qtimetadata';
|
||||
public const QTIMETADATAFIELD = 'qtimetadatafield';
|
||||
public const FIELDLABEL = 'fieldlabel';
|
||||
public const FIELDENTRY = 'fieldentry';
|
||||
public const SECTION = 'section';
|
||||
public const IDENT = 'ident';
|
||||
public const ITEM = 'item';
|
||||
public const TITLE = 'title';
|
||||
public const ITEMMETADATA = 'itemmetadata';
|
||||
public const PRESENTATION = 'presentation';
|
||||
public const MATERIAL = 'material';
|
||||
public const MATTEXT = 'mattext';
|
||||
public const MATREF = 'matref';
|
||||
public const MATBREAK = 'matbreak';
|
||||
public const TEXTTYPE = 'texttype';
|
||||
public const RESPONSE_LID = 'response_lid';
|
||||
public const RENDER_CHOICE = 'render_choice';
|
||||
public const RESPONSE_LABEL = 'response_label';
|
||||
public const RESPROCESSING = 'resprocessing';
|
||||
public const OUTCOMES = 'outcomes';
|
||||
public const DECVAR = 'decvar';
|
||||
public const RESPCONDITION = 'respcondition';
|
||||
public const CONDITIONVAR = 'conditionvar';
|
||||
public const OTHER = 'other';
|
||||
public const DISPLAYFEEDBACK = 'displayfeedback';
|
||||
public const MAXVALUE = 'maxvalue';
|
||||
public const MINVALUE = 'minvalue';
|
||||
public const VARNAME = 'varname';
|
||||
public const VARTYPE = 'vartype';
|
||||
public const CONTINUE_ = 'continue';
|
||||
public const FEEDBACKTYPE = 'feedbacktype';
|
||||
public const LINKREFID = 'linkrefid';
|
||||
public const VAREQUAL = 'varequal';
|
||||
public const RESPIDENT = 'respident';
|
||||
public const ITEMFEEDBACK = 'itemfeedback';
|
||||
public const FLOW_MAT = 'flow_mat';
|
||||
public const RCARDINALITY = 'rcardinality';
|
||||
public const CHARSET = 'charset';
|
||||
public const LABEL = 'label';
|
||||
public const URI = 'uri';
|
||||
public const WIDTH = 'width';
|
||||
public const HEIGHT = 'height';
|
||||
public const X0 = 'x0';
|
||||
public const Y0 = 'y0';
|
||||
public const XML_LANG = 'lang';
|
||||
public const XML_SPACE = 'space';
|
||||
public const RUBRIC = 'rubric';
|
||||
public const ALTMATERIAL = 'altmaterial';
|
||||
public const PRESENTATION_MATERIAL = 'presentation_material';
|
||||
public const T_CLASS = 'class';
|
||||
public const MATERIAL_REF = 'material_ref';
|
||||
public const RTIMING = 'rtiming';
|
||||
public const RENDER_FIB = 'render_fib';
|
||||
public const SHUFFLE = 'shuffle';
|
||||
public const MINNUMBER = 'minnumber';
|
||||
public const MAXNUMBER = 'maxnumber';
|
||||
public const ENCODING = 'encoding';
|
||||
public const MAXCHARS = 'maxchars';
|
||||
public const PROMPT = 'prompt';
|
||||
public const FIBTYPE = 'fibtype';
|
||||
public const ROWS = 'rows';
|
||||
public const COLUMNS = 'columns';
|
||||
public const LABELREFID = 'labelrefid';
|
||||
public const RSHUFFLE = 'rshuffle';
|
||||
public const MATCH_GROUP = 'match_group';
|
||||
public const MATCH_MAX = 'match_max';
|
||||
public const FLOW = 'flow';
|
||||
public const RESPONSE_STR = 'response_str';
|
||||
public const FLOW_LABEL = 'flow_label';
|
||||
public const SETVAR = 'setvar';
|
||||
public const ACTION = 'action';
|
||||
public const AND_ = 'and';
|
||||
public const NOT_ = 'not';
|
||||
public const CASE_ = 'case';
|
||||
public const VARSUBSTRING = 'varsubstring';
|
||||
public const HINT = 'hint';
|
||||
public const SOLUTION = 'solution';
|
||||
public const FEEDBACKSTYLE = 'feedbackstyle';
|
||||
public const SOLUTIONMATERIAL = 'solutionmaterial';
|
||||
public const HINTMATERIAL = 'hintmaterial';
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
abstract class CcQtiValues
|
||||
{
|
||||
public const EXAM_PROFILE = 'cc.exam.v0p1';
|
||||
public const YES = 'Yes';
|
||||
public const NO = 'No';
|
||||
public const RESPONSE = 'Response';
|
||||
public const SOLUTION = 'Solution';
|
||||
public const HINT = 'Hint';
|
||||
public const EXAMINATION = 'Examination';
|
||||
public const PERCENTAGE = 'Percentage';
|
||||
public const UNLIMITED = 'unlimited';
|
||||
public const SINGLE = 'Single';
|
||||
public const MULTIPLE = 'Multiple';
|
||||
public const ORDERER = 'Ordered';
|
||||
public const ASTERISK = 'Asterisk';
|
||||
public const BOX = 'Box';
|
||||
public const DASHLINE = 'Dashline';
|
||||
public const UNDERLINE = 'Underline';
|
||||
public const DECIMAL = 'Decimal';
|
||||
public const INTEGER = 'Integer';
|
||||
public const SCIENTIFIC = 'Scientific';
|
||||
public const STRING = 'String';
|
||||
public const SCORE = 'SCORE';
|
||||
public const SET = 'Set';
|
||||
public const COMPLETE = 'Complete';
|
||||
public const TEXTTYPE = 'text/plain';
|
||||
public const HTMLTYPE = 'text/html';
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcQuestionMetadata extends CcQuestionMetadataBase
|
||||
{
|
||||
/**
|
||||
* Constructs metadata.
|
||||
*
|
||||
* @param string $profile
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct($profile)
|
||||
{
|
||||
if (!CcQtiProfiletype::valid($profile)) {
|
||||
throw new InvalidArgumentException('Invalid profile type!');
|
||||
}
|
||||
$this->setSetting(CcQtiMetadata::CC_PROFILE, $profile);
|
||||
$this->setSetting(CcQtiMetadata::CC_QUESTION_CATEGORY);
|
||||
$this->setSetting(CcQtiMetadata::CC_WEIGHTING);
|
||||
$this->setSetting(CcQtiMetadata::QMD_SCORINGPERMITTED);
|
||||
$this->setSetting(CcQtiMetadata::QMD_COMPUTERSCORED);
|
||||
}
|
||||
|
||||
public function setCategory($value)
|
||||
{
|
||||
$this->setSetting(CcQtiMetadata::CC_QUESTION_CATEGORY, $value);
|
||||
}
|
||||
|
||||
public function setWeighting($value)
|
||||
{
|
||||
$this->setSetting(CcQtiMetadata::CC_WEIGHTING, $value);
|
||||
}
|
||||
|
||||
public function enableScoringpermitted($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiMetadata::QMD_SCORINGPERMITTED, $value);
|
||||
}
|
||||
|
||||
public function enableComputerscored($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiMetadata::QMD_COMPUTERSCORED, $value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcQuestionMetadataBase
|
||||
{
|
||||
protected $metadata = [];
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
*/
|
||||
public function generateAttributes(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
foreach ($this->metadata as $attribute => $value) {
|
||||
if (!is_null($value)) {
|
||||
if (!is_array($value)) {
|
||||
$doc->appendNewAttributeNs($item, $namespace, $attribute, $value);
|
||||
} else {
|
||||
$ns = key($value);
|
||||
$nval = current($value);
|
||||
if (!is_null($nval)) {
|
||||
$doc->appendNewAttributeNs($item, $ns, $attribute, $nval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
*/
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$qtimetadata = $doc->appendNewElementNs($item, $namespace, CcQtiTags::QTIMETADATA);
|
||||
foreach ($this->metadata as $label => $entry) {
|
||||
if (!is_null($entry)) {
|
||||
$qtimetadatafield = $doc->appendNewElementNs($qtimetadata, $namespace, CcQtiTags::QTIMETADATAFIELD);
|
||||
$doc->appendNewElementNs($qtimetadatafield, $namespace, CcQtiTags::FIELDLABEL, $label);
|
||||
$doc->appendNewElementNs($qtimetadatafield, $namespace, CcQtiTags::FIELDENTRY, $entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $setting
|
||||
* @param mixed $value
|
||||
*/
|
||||
protected function setSetting($setting, $value = null)
|
||||
{
|
||||
$this->metadata[$setting] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $setting
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getSetting($setting)
|
||||
{
|
||||
$result = null;
|
||||
if (array_key_exists($setting, $this->metadata)) {
|
||||
$result = $this->metadata[$setting];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $setting
|
||||
* @param string $namespace
|
||||
* @param string $value
|
||||
*/
|
||||
protected function setSettingWns($setting, $namespace, $value = null)
|
||||
{
|
||||
$this->metadata[$setting] = [$namespace => $value];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $setting
|
||||
* @param bool $value
|
||||
*/
|
||||
protected function enableSettingYesno($setting, $value = true)
|
||||
{
|
||||
$svalue = $value ? CcQtiValues::YES : CcQtiValues::NO;
|
||||
$this->setSetting($setting, $svalue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
class CcResponseLidtype extends CcQuestionMetadataBase
|
||||
{
|
||||
protected $tagname = null;
|
||||
protected $material = null;
|
||||
protected $materialRef = null;
|
||||
protected $renderChoice = null;
|
||||
protected $renderFib = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setSetting(CcQtiTags::RCARDINALITY, CcQtiValues::SINGLE);
|
||||
$this->setSetting(CcQtiTags::RTIMING);
|
||||
$this->setSetting(CcQtiTags::IDENT, CcHelpers::uuidgen('I_'));
|
||||
$this->tagname = CcQtiTags::RESPONSE_LID;
|
||||
}
|
||||
|
||||
public function setRcardinality($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::RCARDINALITY, $value);
|
||||
}
|
||||
|
||||
public function enableRtiming($value = true)
|
||||
{
|
||||
$this->enableSettingYesno(CcQtiTags::RTIMING, $value);
|
||||
}
|
||||
|
||||
public function setIdent($value)
|
||||
{
|
||||
$this->setSetting(CcQtiTags::IDENT, $value);
|
||||
}
|
||||
|
||||
public function getIdent()
|
||||
{
|
||||
return $this->getSetting(CcQtiTags::IDENT);
|
||||
}
|
||||
|
||||
public function setMaterialRef(CcAssesmentResponseMatref $object)
|
||||
{
|
||||
$this->materialRef = $object;
|
||||
}
|
||||
|
||||
public function setMaterial(CcAssesmentMaterial $object)
|
||||
{
|
||||
$this->material = $object;
|
||||
}
|
||||
|
||||
public function setRenderChoice(CcAssesmentRenderChoicetype $object)
|
||||
{
|
||||
$this->renderChoice = $object;
|
||||
}
|
||||
|
||||
public function setRenderFib(CcAssesmentRenderFibtype $object)
|
||||
{
|
||||
$this->renderFib = $object;
|
||||
}
|
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace)
|
||||
{
|
||||
$node = $doc->appendNewElementNs($item, $namespace, $this->tagname);
|
||||
$this->generateAttributes($doc, $node, $namespace);
|
||||
|
||||
if (!empty($this->material) && empty($this->materialRef)) {
|
||||
$this->material->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->materialRef) && empty($this->material)) {
|
||||
$this->materialRef->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->renderChoice) && empty($this->renderFib)) {
|
||||
$this->renderChoice->generate($doc, $node, $namespace);
|
||||
}
|
||||
|
||||
if (!empty($this->renderFib) && empty($this->renderChoice)) {
|
||||
$this->renderFib->generate($doc, $node, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/cc_asssesment.php under GNU/GPL license */
|
||||
|
||||
abstract class CcXmlNamespace
|
||||
{
|
||||
public const XML = 'http://www.w3.org/XML/1998/namespace';
|
||||
}
|
||||
238
main/common_cartridge/export/src/lib/ccdependencyparser.php
Normal file
238
main/common_cartridge/export/src/lib/ccdependencyparser.php
Normal file
@@ -0,0 +1,238 @@
|
||||
<?php
|
||||
/* Source: https://github.com/moodle/moodle/blob/MOODLE_310_STABLE/backup/cc/cc_lib/gral_lib/ccdependencyparser.php under GNU/GPL license */
|
||||
|
||||
/**
|
||||
* Converts \ Directory separator to the / more suitable for URL.
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
function toUrlPath(&$path)
|
||||
{
|
||||
for ($count = 0; $count < strlen($path); $count++) {
|
||||
$chr = $path[$count];
|
||||
if (($chr == '\\')) {
|
||||
$path[$count] = '/';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns relative path from two directories with full path.
|
||||
*
|
||||
* @param string $path1
|
||||
* @param string $path2
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function pathDiff($path1, $path2)
|
||||
{
|
||||
toUrlPath($path1);
|
||||
toUrlPath($path2);
|
||||
$result = "";
|
||||
$bl2 = strlen($path2);
|
||||
$a = strpos($path1, $path2);
|
||||
if ($a !== false) {
|
||||
$result = trim(substr($path1, $bl2 + $a), '/');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts direcotry separator in given path to / to validate in CC
|
||||
* Value is passed byref hence variable itself is changed.
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
function toNativePath(&$path)
|
||||
{
|
||||
for ($count = 0; $count < strlen($path); $count++) {
|
||||
$chr = $path[$count];
|
||||
if (($chr == '\\') || ($chr == '/')) {
|
||||
$path[$count] = '/';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function strips url part from css link.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $rootDir
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function stripUrl($path, $rootDir = '')
|
||||
{
|
||||
$result = $path;
|
||||
if (is_string($path) && ($path != '')) {
|
||||
$start = strpos($path, '(') + 1;
|
||||
$length = strpos($path, ')') - $start;
|
||||
$rut = $rootDir.substr($path, $start, $length);
|
||||
$result = fullPath($rut, '/');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $dirsep
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
function fullPath($path, $dirsep = DIRECTORY_SEPARATOR)
|
||||
{
|
||||
$token = '/\$(?:IMS|1EdTech)[-_]CC[-_]FILEBASE\$/';
|
||||
$path = preg_replace($token, '', $path);
|
||||
|
||||
if (is_string($path) && ($path != '')) {
|
||||
$sep = $dirsep;
|
||||
$dotDir = '.';
|
||||
$upDir = '..';
|
||||
$length = strlen($path);
|
||||
$rtemp = trim($path);
|
||||
$start = strrpos($path, $sep);
|
||||
$canContinue = ($start !== false);
|
||||
$result = $canContinue ? '' : $path;
|
||||
$rcount = 0;
|
||||
while ($canContinue) {
|
||||
$dirPart = ($start !== false) ? substr($rtemp, $start + 1, $length - $start) : $rtemp;
|
||||
$canContinue = ($dirPart !== false);
|
||||
if ($canContinue) {
|
||||
if ($dirPart != $dotDir) {
|
||||
if ($dirPart == $upDir) {
|
||||
$rcount++;
|
||||
} else {
|
||||
if ($rcount > 0) {
|
||||
$rcount--;
|
||||
} else {
|
||||
$result = ($result == '') ? $dirPart : $dirPart.$sep.$result;
|
||||
}
|
||||
}
|
||||
}
|
||||
$rtemp = substr($path, 0, $start);
|
||||
$start = strrpos($rtemp, $sep);
|
||||
$canContinue = (($start !== false) || (strlen($rtemp) > 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* validates URL.
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function isUrl($url)
|
||||
{
|
||||
$result = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED) !== false;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dependency files of the $fname file.
|
||||
*
|
||||
* @param string $manifestroot
|
||||
* @param string $fname
|
||||
* @param string $folder
|
||||
* @param array $filenames
|
||||
*/
|
||||
function getDepFiles($manifestroot, $fname, $folder, &$filenames)
|
||||
{
|
||||
static $types = ['xhtml' => true, 'html' => true, 'htm' => true];
|
||||
$extension = strtolower(trim(pathinfo($fname, PATHINFO_EXTENSION)));
|
||||
$filenames = [];
|
||||
if (isset($types[$extension])) {
|
||||
$dcx = new XMLGenericDocument();
|
||||
$filename = $manifestroot.$folder.$fname;
|
||||
if (!file_exists($filename)) {
|
||||
$filename = $manifestroot.DIRECTORY_SEPARATOR.$folder.DIRECTORY_SEPARATOR.$fname;
|
||||
}
|
||||
if (file_exists($filename)) {
|
||||
$res = $dcx->loadHTMLFile($filename);
|
||||
if ($res) {
|
||||
getDepFilesHTML($manifestroot, $fname, $filenames, $dcx, $folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dependency of .html of the $fname file.
|
||||
*
|
||||
* @param string $manifestroot
|
||||
* @param string $fname
|
||||
* @param string $filenames
|
||||
* @param string $dcx
|
||||
* @param string $folder
|
||||
*/
|
||||
function getDepFilesHTML($manifestroot, $fname, &$filenames, &$dcx, $folder)
|
||||
{
|
||||
$dcx->resetXpath();
|
||||
$nlist = $dcx->nodeList("//img/@src | //link/@href | //script/@src | //a[not(starts-with(@href,'#'))]/@href");
|
||||
$cssObjArray = [];
|
||||
foreach ($nlist as $nl) {
|
||||
$item = $folder.$nl->nodeValue;
|
||||
$path_parts = pathinfo($item);
|
||||
$fname = $path_parts['basename'];
|
||||
$ext = array_key_exists('extension', $path_parts) ? $path_parts['extension'] : '';
|
||||
if (!isUrl($folder.$nl->nodeValue) && !isUrl($nl->nodeValue)) {
|
||||
$path = $folder.$nl->nodeValue;
|
||||
$file = fullPath($path, "/");
|
||||
toNativePath($file);
|
||||
if (file_exists($manifestroot.DIRECTORY_SEPARATOR.$file)) {
|
||||
$filenames[$file] = $file;
|
||||
}
|
||||
}
|
||||
if ($ext == 'css') {
|
||||
$css = new CssParser();
|
||||
$css->parse($dcx->filePath().$nl->nodeValue);
|
||||
$cssObjArray[$item] = $css;
|
||||
}
|
||||
}
|
||||
$nlist = $dcx->nodeList("//*/@class");
|
||||
foreach ($nlist as $nl) {
|
||||
$item = $folder.$nl->nodeValue;
|
||||
foreach ($cssObjArray as $csskey => $cssobj) {
|
||||
$bimg = $cssobj->get($item, "background-image");
|
||||
$limg = $cssobj->get($item, "list-style-image");
|
||||
$npath = pathinfo($csskey);
|
||||
if ((!empty($bimg)) && ($bimg != 'none')) {
|
||||
$value = stripUrl($bimg, $npath['dirname'].'/');
|
||||
$filenames[$value] = $value;
|
||||
} elseif ((!empty($limg)) && ($limg != 'none')) {
|
||||
$value = stripUrl($limg, $npath['dirname'].'/');
|
||||
$filenames[$value] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
$elemsToCheck = ["body", "p", "ul", "h4", "a", "th"];
|
||||
$doWeHaveIt = [];
|
||||
foreach ($elemsToCheck as $elem) {
|
||||
$doWeHaveIt[$elem] = ($dcx->nodeList("//".$elem)->length > 0);
|
||||
}
|
||||
foreach ($elemsToCheck as $elem) {
|
||||
if ($doWeHaveIt[$elem]) {
|
||||
foreach ($cssObjArray as $csskey => $cssobj) {
|
||||
$sb = $cssobj->get($elem, "background-image");
|
||||
$sbl = $cssobj->get($elem, "list-style-image");
|
||||
$npath = pathinfo($csskey);
|
||||
if ((!empty($sb)) && ($sb != 'none')) {
|
||||
$value = stripUrl($sb, $npath['dirname'].'/');
|
||||
$filenames[$value] = $value;
|
||||
} elseif ((!empty($sbl)) && ($sbl != 'none')) {
|
||||
$value = stripUrl($sbl, $npath['dirname'].'/');
|
||||
$filenames[$value] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
328
main/common_cartridge/export/src/utils/CcHelpers.php
Normal file
328
main/common_cartridge/export/src/utils/CcHelpers.php
Normal file
@@ -0,0 +1,328 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
abstract class CcHelpers
|
||||
{
|
||||
/**
|
||||
* Checks extension of the supplied filename.
|
||||
*
|
||||
* @param string $filename
|
||||
*/
|
||||
public static function isHtml($filename)
|
||||
{
|
||||
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
|
||||
return in_array($extension, ['htm', 'html']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates unique identifier.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string $suffix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function uuidgen($prefix = '', $suffix = '', $uppercase = true)
|
||||
{
|
||||
$uuid = trim(sprintf('%s%04x%04x%s', $prefix, mt_rand(0, 65535), mt_rand(0, 65535), $suffix));
|
||||
$result = $uppercase ? strtoupper($uuid) : strtolower($uuid);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new folder with random name.
|
||||
*
|
||||
* @param string $where
|
||||
* @param string $prefix
|
||||
* @param string $suffix
|
||||
*
|
||||
* @return mixed - directory short name or false in case of failure
|
||||
*/
|
||||
public static function randomdir($where, $prefix = '', $suffix = '')
|
||||
{
|
||||
$permDirs = api_get_permissions_for_new_directories();
|
||||
|
||||
$dirname = false;
|
||||
$randomname = self::uuidgen($prefix, $suffix, false);
|
||||
$newdirname = $where.DIRECTORY_SEPARATOR.$randomname;
|
||||
if (mkdir($newdirname)) {
|
||||
chmod($newdirname, $permDirs);
|
||||
$dirname = $randomname;
|
||||
}
|
||||
|
||||
return $dirname;
|
||||
}
|
||||
|
||||
public static function buildQuery($attributes, $search)
|
||||
{
|
||||
$result = '';
|
||||
foreach ($attributes as $attribute) {
|
||||
if ($result != '') {
|
||||
$result .= ' | ';
|
||||
}
|
||||
$result .= "//*[starts-with(@{$attribute},'{$search}')]/@{$attribute}";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function processEmbeddedFiles(XMLGenericDocument &$doc, $attributes, $search, $customslash = null)
|
||||
{
|
||||
$result = [];
|
||||
$query = self::buildQuery($attributes, $search);
|
||||
$list = $doc->nodeList($query);
|
||||
foreach ($list as $filelink) {
|
||||
// Prepare the return value of just the filepath from within the course's document folder
|
||||
$rvalue = str_replace($search, '', $filelink->nodeValue);
|
||||
if (!empty($customslash)) {
|
||||
$rvalue = str_replace($customslash, '/', $rvalue);
|
||||
}
|
||||
$result[] = rawurldecode($rvalue);
|
||||
}
|
||||
|
||||
return array_unique($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of embedded files.
|
||||
*
|
||||
* @return multitype:mixed
|
||||
*/
|
||||
public static function embeddedFiles(string $html, string $courseDir = null)
|
||||
{
|
||||
$result = [];
|
||||
$doc = new XMLGenericDocument();
|
||||
$doc->doc->validateOnParse = false;
|
||||
$doc->doc->strictErrorChecking = false;
|
||||
if (!empty($html) && $doc->loadHTML($html)) {
|
||||
$attributes = ['src', 'href'];
|
||||
$result1 = [];
|
||||
if (!empty($courseDir) && is_dir(api_get_path(SYS_COURSE_PATH).$courseDir)) {
|
||||
// get a list of files within the course's "document" directory (only those... for now)
|
||||
$result1 = self::processEmbeddedFiles($doc, $attributes, '/courses/'.$courseDir.'/document/');
|
||||
}
|
||||
$result2 = [];
|
||||
//$result2 = self::processEmbeddedFiles($doc, $attributes, '/app/upload/users/');
|
||||
$result = array_merge($result1, $result2);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of static media dependencies found in a given document file or a document and its neighbours in the same folder.
|
||||
*
|
||||
* @param $packageroot
|
||||
* @param $contextid
|
||||
* @param $folder
|
||||
* @param $docfilepath
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function embeddedMapping($packageroot, $contextid = null, $folder = null, $docfilepath = null)
|
||||
{
|
||||
if (isset($folder)) {
|
||||
$files = array_diff(scandir($folder), ['.', '..']);
|
||||
} else {
|
||||
$folder = dirname($docfilepath);
|
||||
$files[] = basename($docfilepath);
|
||||
}
|
||||
$basePath = api_get_path(SYS_APP_PATH);
|
||||
|
||||
$depfiles = [];
|
||||
foreach ($files as $file) {
|
||||
$mainfile = 1;
|
||||
$filename = $file;
|
||||
$filepath = DIRECTORY_SEPARATOR;
|
||||
$source = '';
|
||||
$author = '';
|
||||
$license = '';
|
||||
$hashedname = '';
|
||||
$hashpart = '';
|
||||
|
||||
$location = $folder.DIRECTORY_SEPARATOR.$file;
|
||||
$type = mime_content_type($basePath.$location);
|
||||
|
||||
$depfiles[$filepath.$filename] = [$location,
|
||||
($mainfile == 1),
|
||||
strtolower(str_replace(' ', '_', $filename)),
|
||||
$type,
|
||||
$source,
|
||||
$author,
|
||||
$license,
|
||||
strtolower(str_replace(' ', '_', $filepath)), ];
|
||||
}
|
||||
|
||||
return $depfiles;
|
||||
}
|
||||
|
||||
public static function addFiles(CcIManifest &$manifest, $packageroot, $outdir, $allinone = true, $folder = null, $docfilepath = null)
|
||||
{
|
||||
$permDirs = api_get_permissions_for_new_directories();
|
||||
|
||||
$files = CcHelpers::embeddedMapping($packageroot, null, $folder, $docfilepath);
|
||||
$basePath = api_get_path(SYS_APP_PATH);
|
||||
|
||||
$rdir = $allinone ? new CcResourceLocation($outdir) : null;
|
||||
foreach ($files as $virtual => $values) {
|
||||
$clean_filename = $values[2];
|
||||
if (!$allinone) {
|
||||
$rdir = new CcResourceLocation($outdir);
|
||||
}
|
||||
$rtp = $rdir->fullpath().$values[7].$clean_filename;
|
||||
//Are there any relative virtual directories?
|
||||
//let us try to recreate them
|
||||
$justdir = $rdir->fullpath(false).$values[7];
|
||||
if (!file_exists($justdir)) {
|
||||
if (!mkdir($justdir, $permDirs, true)) {
|
||||
throw new RuntimeException('Unable to create directories!');
|
||||
}
|
||||
}
|
||||
|
||||
$source = $values[0];
|
||||
if (is_dir($basePath.$source)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!copy($basePath.$source, $rtp)) {
|
||||
throw new RuntimeException('Unable to copy files from '.$basePath.$source.' to '.$rtp.'!');
|
||||
}
|
||||
$resource = new CcResources($rdir->rootdir(),
|
||||
$values[7].$clean_filename,
|
||||
$rdir->dirname(false));
|
||||
|
||||
$res = $manifest->addResource($resource, null, CcVersion13::WEBCONTENT);
|
||||
|
||||
PkgStaticResources::instance()->add($virtual,
|
||||
$res[0],
|
||||
$rdir->dirname(false).$values[7].$clean_filename,
|
||||
$values[1],
|
||||
$resource);
|
||||
}
|
||||
|
||||
PkgStaticResources::instance()->finished = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Excerpt from IMS CC 1.1 overview :
|
||||
* No spaces in filenames, directory and file references should
|
||||
* employ all lowercase or all uppercase - no mixed case.
|
||||
*
|
||||
* @param string $packageroot
|
||||
* @param int $contextid
|
||||
* @param string $outdir
|
||||
* @param bool $allinone
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function handleStaticContent(CcIManifest &$manifest, $packageroot, $contextid, $outdir, $allinone = true, $folder = null)
|
||||
{
|
||||
self::addFiles($manifest, $packageroot, $outdir, $allinone, $folder);
|
||||
|
||||
return PkgStaticResources::instance()->getValues();
|
||||
}
|
||||
|
||||
public static function handleResourceContent(CcIManifest &$manifest, $packageroot, $contextid, $outdir, $allinone = true, $docfilepath = null)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
self::addFiles($manifest, $packageroot, $outdir, $allinone, null, $docfilepath);
|
||||
|
||||
$files = self::embeddedMapping($packageroot, $contextid, null, $docfilepath);
|
||||
$rootnode = null;
|
||||
$rootvals = null;
|
||||
$depfiles = [];
|
||||
$depres = [];
|
||||
$flocation = null;
|
||||
foreach ($files as $virtual => $values) {
|
||||
$vals = PkgStaticResources::instance()->getIdentifier($virtual);
|
||||
$resource = $vals[3];
|
||||
$identifier = $resource->identifier;
|
||||
$flocation = $vals[1];
|
||||
if ($values[1]) {
|
||||
$rootnode = $resource;
|
||||
$rootvals = $flocation;
|
||||
continue;
|
||||
}
|
||||
$depres[] = $identifier;
|
||||
$depfiles[] = $vals[1];
|
||||
$result[$virtual] = [$identifier, $flocation, false];
|
||||
}
|
||||
|
||||
if (!empty($rootnode)) {
|
||||
$rootnode->files = array_merge($rootnode->files, $depfiles);
|
||||
$result[$virtual] = [$rootnode->identifier, $rootvals, true];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect embedded files in the given HTML string.
|
||||
*
|
||||
* @param string $content The HTML string content
|
||||
* @param CcIManifest $manifest Manifest object (usually empty at this point) that will be filled
|
||||
* @param $packageroot
|
||||
* @param $contextid
|
||||
* @param $outdir
|
||||
* @param $webcontent
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function processLinkedFiles(
|
||||
string $content,
|
||||
CcIManifest &$manifest,
|
||||
$packageroot,
|
||||
$contextid,
|
||||
$outdir,
|
||||
$webcontent = false
|
||||
) {
|
||||
// Detect all embedded files
|
||||
// copy all files in the cc package stripping any spaces and using only lowercase letters
|
||||
// add those files as resources of the type webcontent to the manifest
|
||||
// replace the links to the resource using $1Edtech-CC-FILEBASE$ and their new locations
|
||||
// cc_resource has array of files and array of dependencies
|
||||
// most likely we would need to add all files as independent resources and than
|
||||
// attach them all as dependencies to the forum tag.
|
||||
$courseDir = $internalCourseDocumentsPath = null;
|
||||
$courseInfo = api_get_course_info();
|
||||
$replaceprefix = '$1EdTech-CC-FILEBASE$';
|
||||
$tokenSyntax = api_get_configuration_value('commoncartridge_path_token');
|
||||
if (!empty($tokenSyntax)) {
|
||||
$replaceprefix = $tokenSyntax;
|
||||
}
|
||||
if (!empty($courseInfo)) {
|
||||
$courseDir = $courseInfo['directory'];
|
||||
$internalCourseDocumentsPath = '/courses/'.$courseDir.'/document';
|
||||
}
|
||||
$lfiles = self::embeddedFiles($content, $courseDir);
|
||||
$text = $content;
|
||||
$deps = [];
|
||||
if (!empty($lfiles)) {
|
||||
foreach ($lfiles as $lfile) {
|
||||
$lfile = DIRECTORY_SEPARATOR.$lfile; // results of handleResourceContent() come prefixed by DIRECTORY_SEPARATOR
|
||||
$files = self::handleResourceContent(
|
||||
$manifest,
|
||||
$packageroot,
|
||||
$contextid,
|
||||
$outdir,
|
||||
true,
|
||||
$internalCourseDocumentsPath.$lfile
|
||||
);
|
||||
$bfile = DIRECTORY_SEPARATOR.basename($lfile);
|
||||
if (isset($files[$bfile])) {
|
||||
$filename = str_replace('%2F', '/', rawurlencode($lfile));
|
||||
$content = str_replace($internalCourseDocumentsPath.$filename,
|
||||
$replaceprefix.'../'.$files[$bfile][1],
|
||||
$content);
|
||||
$deps[] = $files[$bfile][0];
|
||||
}
|
||||
}
|
||||
$text = $content;
|
||||
}
|
||||
|
||||
return [$text, $deps];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
final class CcResourceLocation
|
||||
{
|
||||
/**
|
||||
* Root directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $rootdir = null;
|
||||
/**
|
||||
* new directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $dir = null;
|
||||
/**
|
||||
* Full precalculated path.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $fullpath = null;
|
||||
|
||||
/**
|
||||
* ctor.
|
||||
*
|
||||
* @param string $rootdir - path to the containing directory
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function __construct($rootdir)
|
||||
{
|
||||
$rdir = realpath($rootdir);
|
||||
if (empty($rdir)) {
|
||||
throw new InvalidArgumentException('Invalid path!');
|
||||
}
|
||||
$dir = CcHelpers::randomdir($rdir, 'i_');
|
||||
if ($dir === false) {
|
||||
throw new RuntimeException('Unable to create directory!');
|
||||
}
|
||||
$this->rootdir = $rdir;
|
||||
$this->dir = $dir;
|
||||
$this->fullpath = $rdir.DIRECTORY_SEPARATOR.$dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Newly created directory.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dirname($endseparator = false)
|
||||
{
|
||||
return $this->dir.($endseparator ? '/' : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Full path to the new directory.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fullpath($endseparator = false)
|
||||
{
|
||||
return $this->fullpath.($endseparator ? DIRECTORY_SEPARATOR : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns containing dir.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function rootdir($endseparator = false)
|
||||
{
|
||||
return $this->rootdir.($endseparator ? DIRECTORY_SEPARATOR : '');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
class PkgResourceDependencies
|
||||
{
|
||||
private $values = [];
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* @return PkgResourceDependencies
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
if (empty(self::$instance)) {
|
||||
$c = __CLASS__;
|
||||
self::$instance = new $c();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function add(array $deps)
|
||||
{
|
||||
$this->values = array_merge($this->values, $deps);
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->values = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDeps()
|
||||
{
|
||||
return $this->values;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
class PkgStaticResources
|
||||
{
|
||||
public $finished = false;
|
||||
|
||||
private $values = [];
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* @return PkgStaticResources
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
if (empty(self::$instance)) {
|
||||
$c = __CLASS__;
|
||||
self::$instance = new $c();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* add new element.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param string $file
|
||||
* @param bool $main
|
||||
*/
|
||||
public function add($key, $identifier, $file, $main, $node = null)
|
||||
{
|
||||
$this->values[$key] = [$identifier, $file, $main, $node];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getValues()
|
||||
{
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
public function getIdentifier($location)
|
||||
{
|
||||
return isset($this->values[$location]) ? $this->values[$location] : false;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->values = [];
|
||||
$this->finished = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user