Course maintenance: Add support for IMS Common Cartridge 1.3 import and export - refs #2747
Authored-by: Christian <christianbeeznest@users.noreply.github.com>pull/3952/head
parent
3ebaffa9e0
commit
47915cfb17
@ -0,0 +1,92 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php'; |
||||
require_once api_get_path(SYS_CODE_PATH).'common_cartridge/export/src/lib/ccdependencyparser.php'; |
||||
use Chamilo\CourseBundle\Component\CourseCopy\CourseArchiver; |
||||
use Chamilo\CourseBundle\Component\CourseCopy\CourseBuilder; |
||||
use Chamilo\CourseBundle\Component\CourseCopy\CourseSelectForm; |
||||
|
||||
$current_course_tool = TOOL_COURSE_MAINTENANCE; |
||||
|
||||
api_protect_course_script(true); |
||||
|
||||
// Check access rights (only teachers are allowed here) |
||||
if (!api_is_allowed_to_edit()) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
api_check_archive_dir(); |
||||
api_set_more_memory_and_time_limits(); |
||||
|
||||
// Section for the tabs |
||||
$this_section = SECTION_COURSES; |
||||
|
||||
// Breadcrumbs |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'course_info/maintenance.php', |
||||
'name' => get_lang('Maintenance'), |
||||
]; |
||||
|
||||
// Displaying the header |
||||
$nameTools = get_lang('ExportCcVersion13'); |
||||
Display::display_header($nameTools); |
||||
|
||||
// Display the tool title |
||||
echo Display::page_header($nameTools); |
||||
|
||||
$action = isset($_POST['action']) ? $_POST['action'] : ''; |
||||
$backupOption = 'select_items'; |
||||
|
||||
if (Security::check_token('post') && ($action === 'course_select_form')) { |
||||
// Clear token |
||||
Security::clear_token(); |
||||
$resources = Security::remove_XSS($_POST['resource']); |
||||
if (!empty($resources)) { |
||||
$cb = new CourseBuilder('partial'); |
||||
$course = $cb->build(0, null, false, array_keys($resources), $resources); |
||||
$course = CourseSelectForm::get_posted_course(null, 0, '', $course); |
||||
$imsccFile = Cc13ExportConvert::export($course); |
||||
if ($imsccFile !== false) { |
||||
echo Display::return_message(get_lang('ImsccCreated'), 'confirm'); |
||||
echo '<br />'; |
||||
echo Display::toolbarButton( |
||||
get_lang('Download'), |
||||
api_get_path(WEB_CODE_PATH).'course_info/download.php?archive='.$imsccFile.'&'.api_get_cidreq(), |
||||
'file-zip-o', |
||||
'primary' |
||||
); |
||||
/*echo Display::url( |
||||
get_lang('Download'), |
||||
api_get_path(WEB_CODE_PATH).'course_info/download.php?archive='.$imsccFile.'&'.api_get_cidreq(), |
||||
['class' => 'btn btn-primary btn-large'] |
||||
);*/ |
||||
} |
||||
} |
||||
} else { |
||||
// Clear token |
||||
Security::clear_token(); |
||||
$cb = new CourseBuilder('partial'); |
||||
$toolsToBuild = [ |
||||
RESOURCE_DOCUMENT, |
||||
RESOURCE_FORUMCATEGORY, |
||||
RESOURCE_FORUM, |
||||
RESOURCE_FORUMTOPIC, |
||||
RESOURCE_QUIZ, |
||||
RESOURCE_TEST_CATEGORY, |
||||
RESOURCE_LINK, |
||||
RESOURCE_WIKI, |
||||
]; |
||||
$course = $cb->build(0, null, false, $toolsToBuild); |
||||
if ($course->has_resources()) { |
||||
// Add token to Course select form |
||||
$hiddenFields['sec_token'] = Security::get_token(); |
||||
CourseSelectForm::display_form($course, $hiddenFields, false, true, true); |
||||
} else { |
||||
echo Display::return_message(get_lang('NoResourcesToBackup'), 'warning'); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
Display::display_footer(); |
||||
@ -0,0 +1,75 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php'; |
||||
require_once api_get_path(SYS_CODE_PATH).'common_cartridge/import/src/lib/validateurlsyntax.php'; |
||||
require_once api_get_path(SYS_CODE_PATH).'common_cartridge/import/src/inc/constants.php'; |
||||
|
||||
$current_course_tool = TOOL_COURSE_MAINTENANCE; |
||||
api_protect_course_script(true); |
||||
|
||||
// Check access rights (only teachers are allowed here) |
||||
if (!api_is_allowed_to_edit()) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
api_set_more_memory_and_time_limits(); |
||||
|
||||
// Section for the tabs |
||||
$this_section = SECTION_COURSES; |
||||
|
||||
// Breadcrumbs |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_CODE_PATH).'course_info/maintenance.php?'.api_get_cidreq(), |
||||
'name' => get_lang('Maintenance'), |
||||
]; |
||||
|
||||
$form = new FormValidator('cc_import', 'post', api_get_self().'?'.api_get_cidreq()); |
||||
$form->addFile('cc_file', get_lang('ImsccFile')); |
||||
$form->addButtonImport(get_lang('Import')); |
||||
|
||||
if ($form->validate()) { |
||||
$file = $_FILES['cc_file']; |
||||
|
||||
if (empty($file['tmp_name'])) { |
||||
$errorMessage = get_lang('UplUploadFailed'); |
||||
echo Display::return_message($errorMessage, 'error', false); |
||||
} else { |
||||
$allowedFileMimetype = ['imscc']; |
||||
|
||||
$extImportFile = substr($file['name'], (strrpos($file['name'], '.') + 1)); |
||||
|
||||
if (!in_array($extImportFile, $allowedFileMimetype)) { |
||||
echo Display::return_message(get_lang('YouMustImportAFileAccordingToSelectedOption'), 'error'); |
||||
} else { |
||||
$baseDir = api_get_path(SYS_ARCHIVE_PATH); |
||||
$uploadPath = 'imsccImport/'; |
||||
$errors = []; |
||||
if (!is_dir($baseDir.$uploadPath)) { |
||||
@mkdir($baseDir.$uploadPath); |
||||
} |
||||
|
||||
$filepath = $baseDir.$uploadPath; |
||||
|
||||
if (!Imscc13Import::unzip($file['tmp_name'], $filepath)) { |
||||
return false; |
||||
} |
||||
|
||||
// We detect if it is cc v1.3 |
||||
$detected = Imscc13Import::detectFormat($filepath); |
||||
if ($detected) { |
||||
Imscc13Import::execute($filepath); |
||||
Display::addFlash(Display::return_message(get_lang('CcFileImported'), 'normal', false)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
$template = new Template(get_lang('ImportCcVersion13')); |
||||
Display::addFlash(Display::return_message(get_lang('ImportCcInstructions'), 'normal', false)); |
||||
$template->assign('form', $form->returnForm()); |
||||
$templateName = $template->get_template('common_cartridge/import_cc.tpl'); |
||||
$content = $template->fetch($templateName); |
||||
$template->assign('header', get_lang('ImportCcVersion13')); |
||||
$template->assign('content', $content); |
||||
$template->display_one_col_template(); |
||||
@ -0,0 +1,291 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
class Cc13Convert |
||||
{ |
||||
public static function convert($packagedir, $outdir, $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'], 'quiz', $count, $objCourse->info['code'], $resources['Exercise_Question']); |
||||
$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; |
||||
} |
||||
|
||||
protected static function getItemSections($itemData, $itemType, &$count, $courseCode, $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; |
||||
} |
||||
|
||||
protected static function getSequence($objItems, $categoryId = null, $itemType = null, $coursecode = null, $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]; |
||||
} |
||||
} |
||||
$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; |
||||
} |
||||
|
||||
protected static function processSequence(CcIItem &$item, CcIManifest &$manifest, array $sequence, $packageroot, $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, $path); |
||||
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; |
||||
} |
||||
} |
||||
@ -0,0 +1,46 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
use Chamilo\CourseBundle\Component\CourseCopy\CourseArchiver; |
||||
|
||||
class Cc13ExportConvert |
||||
{ |
||||
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; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
} |
||||
@ -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 |
||||
{ |
||||
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; |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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])); |
||||
} |
||||
} |
||||
@ -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]; |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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)); |
||||
} |
||||
} |
||||
@ -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(); |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -0,0 +1,102 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
class CcVersion13 extends CcVersion1 |
||||
{ |
||||
const WEBCONTENT = 'webcontent'; |
||||
const QUESTIONBANK = 'imsqti_xmlv1p3/imscc_xmlv1p3/question-bank'; |
||||
const ASSESSMENT = 'imsqti_xmlv1p3/imscc_xmlv1p3/assessment'; |
||||
const ASSOCIATEDCONTENT = 'associatedcontent/imscc_xmlv1p3/learning-application-resource'; |
||||
const DISCUSSIONTOPIC = 'imsdt_xmlv1p3'; |
||||
const WEBLINK = 'imswl_xmlv1p3'; |
||||
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); |
||||
} |
||||
} |
||||
} |
||||
@ -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 |
||||
{ |
||||
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; |
||||
} |
||||
} |
||||
@ -0,0 +1,88 @@ |
||||
<?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 CcIItem $item |
||||
* @param CcIManifest $manifest |
||||
* @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}!"); |
||||
} |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -0,0 +1,520 @@ |
||||
<?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 |
||||
{ |
||||
const WEBCONTENT = 'webcontent'; |
||||
const QUESTIONBANK = 'imsqti_xmlv1p2/imscc_xmlv1p0/question-bank'; |
||||
const ASSESSMENT = 'imsqti_xmlv1p2/imscc_xmlv1p0/assessment'; |
||||
const ASSOCIATEDCONTENT = 'associatedcontent/imscc_xmlv1p0/learning-application-resource'; |
||||
const DISCUSSIONTOPIC = 'imsdt_xmlv1p0'; |
||||
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 CcIResource $res |
||||
* @param DOMDocument $doc |
||||
* @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 CcIOrganization $org |
||||
* @param DOMDocument $doc |
||||
* @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 CcIOrganization $org |
||||
* @param DOMDocument $doc |
||||
* @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 CcIMetadataManifest $met |
||||
* @param DOMDocument $doc |
||||
* @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 CcIMetadataResource $met |
||||
* @param DOMDocument $doc |
||||
* @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 CcIMetadataFile $met |
||||
* @param DOMDocument $doc |
||||
* @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 DOMDocument $doc |
||||
* @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; |
||||
} |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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] : ''; |
||||
} |
||||
} |
||||
} |
||||
@ -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,80 @@ |
||||
<?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, $rootpath, $path) |
||||
{ |
||||
$this->ccType = CcVersion13::ASSESSMENT; |
||||
$this->defaultfile = 'quiz.xml'; |
||||
$this->defaultname = Assesment13ResourceFile::DEAFULTNAME; |
||||
parent::__construct($item, $manifest, $rootpath, $path); |
||||
} |
||||
|
||||
public function convert($outdir, $objQuizz) |
||||
{ |
||||
$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); |
||||
|
||||
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; |
||||
} |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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 |
||||
{ |
||||
const DEAFULTNAME = 'assesment.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,135 @@ |
||||
<?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 unknown_type $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 : |
||||
* 1 : Unique Answer (Multiple choice, single response) |
||||
* 2 : Multiple Answers (Multiple choice, multiple response) |
||||
* |
||||
*/ |
||||
$questionProcessor = null; |
||||
switch ($qtype) { |
||||
case 1: |
||||
$questionProcessor = new CcAssesmentQuestionMultichoice($objQuizz, $objQuizz['questions'], $manifest, $section, $question, $rootpath, $contextid, $outdir); |
||||
$questionProcessor->generate(); |
||||
$questioncount++; |
||||
break; |
||||
case 2: |
||||
$questionProcessor = new CcAssesmentQuestionMultichoiceMultiresponse($objQuizz, $objQuizz['questions'], $manifest, $section, $question, $rootpath, $contextid, $outdir); |
||||
$questionProcessor->generate(); |
||||
$questioncount++; |
||||
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,216 @@ |
||||
<?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->correctAnswerIdent = $answerIdent; |
||||
} |
||||
|
||||
//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; |
||||
} |
||||
} |
||||
$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,155 @@ |
||||
<?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 |
||||
$questionCategory = $this->questionNode->questionCategory; |
||||
|
||||
if (!empty($questionCategory)) { |
||||
$this->qmetadata->setCategory($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; |
||||
$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,106 @@ |
||||
<?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 $material = null; |
||||
protected $materialRef = null; |
||||
protected $responseLabel = null; |
||||
protected $flowLabel = null; |
||||
|
||||
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); |
||||
} |
||||
|
||||
public function setEncoding($value) |
||||
{ |
||||
$this->setSetting(CcQtiTags::ENCODING, $value); |
||||
} |
||||
|
||||
public function setCharset($value) |
||||
{ |
||||
$this->setSetting(CcQtiTags::CHARSET, $value); |
||||
} |
||||
|
||||
public function setRows($value) |
||||
{ |
||||
$this->setSetting(CcQtiTags::ROWS, $value); |
||||
} |
||||
|
||||
public function setColumns($value) |
||||
{ |
||||
$this->setSetting(CcQtiTags::COLUMNS, $value); |
||||
} |
||||
|
||||
public function setMaxchars($value) |
||||
{ |
||||
$this->setSetting(CcQtiTags::COLUMNS, $value); |
||||
} |
||||
|
||||
public function setLimits($min = null, $max = null) |
||||
{ |
||||
$this->setSetting(CcQtiTags::MINNUMBER, $min); |
||||
$this->setSetting(CcQtiTags::MAXNUMBER, $max); |
||||
} |
||||
|
||||
public function setPrompt($value) |
||||
{ |
||||
$this->setSetting(CcQtiTags::PROMPT, $value); |
||||
} |
||||
|
||||
public function setFibtype($value) |
||||
{ |
||||
$this->setSetting(CcQtiTags::FIBTYPE, $value); |
||||
} |
||||
|
||||
public function setMaterial(CcAssesmentMaterial $object) |
||||
{ |
||||
$this->material = $object; |
||||
} |
||||
|
||||
public function setMaterialRef(CcAssesmentResponseMatref $object) |
||||
{ |
||||
$this->materialRef = $object; |
||||
} |
||||
|
||||
public function setResponseLabel(CcAssesmentResponseLabeltype $object) |
||||
{ |
||||
$this->responseLabel = $object; |
||||
} |
||||
|
||||
public function setFlowLabel($object) |
||||
{ |
||||
$this->flowLabel = $object; |
||||
} |
||||
|
||||
public function generate(XMLGenericDocument &$doc, DOMNode &$item, $namespace) |
||||
{ |
||||
$node = $doc->appendNewElementNs($item, $namespace, CcQtiTags::RENDER_FIB); |
||||
$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->responseLabel)) { |
||||
$this->responseLabel->generate($doc, $node, $namespace); |
||||
} |
||||
|
||||
if (!empty($this->flowLabel)) { |
||||
$this->flowLabel->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. |
||||
const QMD_ASSESSMENTTYPE = 'qmd_assessmenttype'; |
||||
const QMD_SCORETYPE = 'qmd_scoretype'; |
||||
const QMD_FEEDBACKPERMITTED = 'qmd_feedbackpermitted'; |
||||
const QMD_HINTSPERMITTED = 'qmd_hintspermitted'; |
||||
const QMD_SOLUTIONSPERMITTED = 'qmd_solutionspermitted'; |
||||
const QMD_TIMELIMIT = 'qmd_timelimit'; |
||||
const CC_ALLOW_LATE_SUBMISSION = 'cc_allow_late_submission'; |
||||
const CC_MAXATTEMPTS = 'cc_maxattempts'; |
||||
const CC_PROFILE = 'cc_profile'; |
||||
|
||||
// Items. |
||||
const CC_WEIGHTING = 'cc_weighting'; |
||||
const QMD_SCORINGPERMITTED = 'qmd_scoringpermitted'; |
||||
const QMD_COMPUTERSCORED = 'qmd_computerscored'; |
||||
const CC_QUESTION_CATEGORY = 'cc_question_category'; |
||||
} |
||||
@ -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 */ |
||||
|
||||
abstract class CcQtiProfiletype |
||||
{ |
||||
const MULTIPLE_CHOICE = 'cc.multiple_choice.v0p1'; |
||||
const MULTIPLE_RESPONSE = 'cc.multiple_response.v0p1'; |
||||
const TRUE_FALSE = 'cc.true_false.v0p1'; |
||||
const FIELD_ENTRY = 'cc.fib.v0p1'; |
||||
const PATTERN_MATCH = 'cc.pattern_match.v0p1'; |
||||
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); |
||||
} |
||||
} |
||||
@ -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 |
||||
{ |
||||
const QUESTESTINTEROP = 'questestinterop'; |
||||
const ASSESSMENT = 'assessment'; |
||||
const QTIMETADATA = 'qtimetadata'; |
||||
const QTIMETADATAFIELD = 'qtimetadatafield'; |
||||
const FIELDLABEL = 'fieldlabel'; |
||||
const FIELDENTRY = 'fieldentry'; |
||||
const SECTION = 'section'; |
||||
const IDENT = 'ident'; |
||||
const ITEM = 'item'; |
||||
const TITLE = 'title'; |
||||
const ITEMMETADATA = 'itemmetadata'; |
||||
const PRESENTATION = 'presentation'; |
||||
const MATERIAL = 'material'; |
||||
const MATTEXT = 'mattext'; |
||||
const MATREF = 'matref'; |
||||
const MATBREAK = 'matbreak'; |
||||
const TEXTTYPE = 'texttype'; |
||||
const RESPONSE_LID = 'response_lid'; |
||||
const RENDER_CHOICE = 'render_choice'; |
||||
const RESPONSE_LABEL = 'response_label'; |
||||
const RESPROCESSING = 'resprocessing'; |
||||
const OUTCOMES = 'outcomes'; |
||||
const DECVAR = 'decvar'; |
||||
const RESPCONDITION = 'respcondition'; |
||||
const CONDITIONVAR = 'conditionvar'; |
||||
const OTHER = 'other'; |
||||
const DISPLAYFEEDBACK = 'displayfeedback'; |
||||
const MAXVALUE = 'maxvalue'; |
||||
const MINVALUE = 'minvalue'; |
||||
const VARNAME = 'varname'; |
||||
const VARTYPE = 'vartype'; |
||||
const CONTINUE_ = 'continue'; |
||||
const FEEDBACKTYPE = 'feedbacktype'; |
||||
const LINKREFID = 'linkrefid'; |
||||
const VAREQUAL = 'varequal'; |
||||
const RESPIDENT = 'respident'; |
||||
const ITEMFEEDBACK = 'itemfeedback'; |
||||
const FLOW_MAT = 'flow_mat'; |
||||
const RCARDINALITY = 'rcardinality'; |
||||
const CHARSET = 'charset'; |
||||
const LABEL = 'label'; |
||||
const URI = 'uri'; |
||||
const WIDTH = 'width'; |
||||
const HEIGHT = 'height'; |
||||
const X0 = 'x0'; |
||||
const Y0 = 'y0'; |
||||
const XML_LANG = 'lang'; |
||||
const XML_SPACE = 'space'; |
||||
const RUBRIC = 'rubric'; |
||||
const ALTMATERIAL = 'altmaterial'; |
||||
const PRESENTATION_MATERIAL = 'presentation_material'; |
||||
const T_CLASS = 'class'; |
||||
const MATERIAL_REF = 'material_ref'; |
||||
const RTIMING = 'rtiming'; |
||||
const RENDER_FIB = 'render_fib'; |
||||
const SHUFFLE = 'shuffle'; |
||||
const MINNUMBER = 'minnumber'; |
||||
const MAXNUMBER = 'maxnumber'; |
||||
const ENCODING = 'encoding'; |
||||
const MAXCHARS = 'maxchars'; |
||||
const PROMPT = 'prompt'; |
||||
const FIBTYPE = 'fibtype'; |
||||
const ROWS = 'rows'; |
||||
const COLUMNS = 'columns'; |
||||
const LABELREFID = 'labelrefid'; |
||||
const RSHUFFLE = 'rshuffle'; |
||||
const MATCH_GROUP = 'match_group'; |
||||
const MATCH_MAX = 'match_max'; |
||||
const FLOW = 'flow'; |
||||
const RESPONSE_STR = 'response_str'; |
||||
const FLOW_LABEL = 'flow_label'; |
||||
const SETVAR = 'setvar'; |
||||
const ACTION = 'action'; |
||||
const AND_ = 'and'; |
||||
const NOT_ = 'not'; |
||||
const CASE_ = 'case'; |
||||
const VARSUBSTRING = 'varsubstring'; |
||||
const HINT = 'hint'; |
||||
const SOLUTION = 'solution'; |
||||
const FEEDBACKSTYLE = 'feedbackstyle'; |
||||
const SOLUTIONMATERIAL = 'solutionmaterial'; |
||||
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 |
||||
{ |
||||
const EXAM_PROFILE = 'cc.exam.v0p1'; |
||||
const YES = 'Yes'; |
||||
const NO = 'No'; |
||||
const RESPONSE = 'Response'; |
||||
const SOLUTION = 'Solution'; |
||||
const HINT = 'Hint'; |
||||
const EXAMINATION = 'Examination'; |
||||
const PERCENTAGE = 'Percentage'; |
||||
const UNLIMITED = 'unlimited'; |
||||
const SINGLE = 'Single'; |
||||
const MULTIPLE = 'Multiple'; |
||||
const ORDERER = 'Ordered'; |
||||
const ASTERISK = 'Asterisk'; |
||||
const BOX = 'Box'; |
||||
const DASHLINE = 'Dashline'; |
||||
const UNDERLINE = 'Underline'; |
||||
const DECIMAL = 'Decimal'; |
||||
const INTEGER = 'Integer'; |
||||
const SCIENTIFIC = 'Scientific'; |
||||
const STRING = 'String'; |
||||
const SCORE = 'SCORE'; |
||||
const SET = 'Set'; |
||||
const COMPLETE = 'Complete'; |
||||
const TEXTTYPE = 'text/plain'; |
||||
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 |
||||
{ |
||||
const XML = 'http://www.w3.org/XML/1998/namespace'; |
||||
} |
||||
@ -0,0 +1,236 @@ |
||||
<?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-CC-FILEBASE$'; |
||||
$path = str_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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,283 @@ |
||||
<?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(&$doc, $attributes, $search, $customslash = null) |
||||
{ |
||||
$result = []; |
||||
$query = self::buildQuery($attributes, $search); |
||||
$list = $doc->nodeList($query); |
||||
foreach ($list as $filelink) { |
||||
$rvalue = str_replace($search, '', $filelink->nodeValue); |
||||
if (!empty($customslash)) { |
||||
$rvalue = str_replace($customslash, '/', $rvalue); |
||||
} |
||||
$result[] = rawurldecode($rvalue); |
||||
} |
||||
|
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* Get list of embedded files. |
||||
* |
||||
* @param string $html |
||||
* |
||||
* @return multitype:mixed |
||||
*/ |
||||
public static function embeddedFiles($html) |
||||
{ |
||||
$result = []; |
||||
$doc = new XMLGenericDocument(); |
||||
$doc->doc->validateOnParse = false; |
||||
$doc->doc->strictErrorChecking = false; |
||||
if (!empty($html) && $doc->loadHTML($html)) { |
||||
$attributes = ['src', 'href']; |
||||
$result1 = self::processEmbeddedFiles($doc, $attributes, '@@PLUGINFILE@@'); |
||||
$result2 = self::processEmbeddedFiles($doc, $attributes, '$@FILEPHP@$', '$@SLASH@$'); |
||||
$result = array_merge($result1, $result2); |
||||
} |
||||
|
||||
return $result; |
||||
} |
||||
|
||||
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); |
||||
} |
||||
|
||||
$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($file); |
||||
|
||||
$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); |
||||
|
||||
$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($source)) { |
||||
continue; |
||||
} |
||||
|
||||
if (!copy($source, $rtp)) { |
||||
throw new RuntimeException('Unable to copy files!'); |
||||
} |
||||
$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; |
||||
} |
||||
|
||||
public static function processLinkedFiles($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 $IMS-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. |
||||
$lfiles = self::embeddedFiles($content); |
||||
$text = $content; |
||||
$deps = []; |
||||
if (!empty($lfiles)) { |
||||
$files = self::handleStaticContent($manifest, |
||||
$packageroot, |
||||
$contextid, |
||||
$outdir); |
||||
$replaceprefix = $webcontent ? '' : '$IMS-CC-FILEBASE$'; |
||||
foreach ($lfiles as $lfile) { |
||||
if (isset($files[$lfile])) { |
||||
$filename = str_replace('%2F', '/', rawurlencode($lfile)); |
||||
$content = str_replace('@@PLUGINFILE@@'.$filename, |
||||
$replaceprefix.'../'.$files[$lfile][1], |
||||
$content); |
||||
// For the legacy stuff. |
||||
$content = str_replace('$@FILEPHP@$'.str_replace('/', '$@SLASH@$', $filename), |
||||
$replaceprefix.'../'.$files[$lfile][1], |
||||
$content); |
||||
$deps[] = $files[$lfile][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; |
||||
} |
||||
} |
||||
@ -0,0 +1,66 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
class Cc1p3Convert extends CcBase |
||||
{ |
||||
const CC_TYPE_FORUM = 'imsdt_xmlv1p3'; |
||||
const CC_TYPE_QUIZ = 'imsqti_xmlv1p3/imscc_xmlv1p3/assessment'; |
||||
const CC_TYPE_QUESTION_BANK = 'imsqti_xmlv1p3/imscc_xmlv1p3/question-bank'; |
||||
const CC_TYPE_WEBLINK = 'imswl_xmlv1p3'; |
||||
const CC_TYPE_ASSOCIATED_CONTENT = 'associatedcontent/imscc_xmlv1p3/learning-application-resource'; |
||||
const CC_TYPE_BASICLTI = 'imsbasiclti_xmlv1p3'; |
||||
|
||||
public static $namespaces = ['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', ]; |
||||
|
||||
public static $restypes = ['associatedcontent/imscc_xmlv1p3/learning-application-resource', 'webcontent']; |
||||
public static $forumns = ['dt' => 'http://www.imsglobal.org/xsd/imsccv1p3/imsdt_v1p3']; |
||||
public static $quizns = ['xmlns' => 'http://www.imsglobal.org/xsd/ims_qtiasiv1p2']; |
||||
public static $resourcens = ['wl' => 'http://www.imsglobal.org/xsd/imsccv1p3/imswl_v1p3']; |
||||
public static $basicltins = [ |
||||
'xmlns' => 'http://www.imsglobal.org/xsd/imslticc_v1p0', |
||||
'blti' => 'http://www.imsglobal.org/xsd/imsbasiclti_v1p0', |
||||
'lticm' => 'http://www.imsglobal.org/xsd/imslticm_v1p0', |
||||
'lticp' => 'http://www.imsglobal.org/xsd/imslticp_v1p0', |
||||
]; |
||||
|
||||
public function __construct($path_to_manifest) |
||||
{ |
||||
parent::__construct($path_to_manifest); |
||||
} |
||||
|
||||
public function generateImportData() |
||||
{ |
||||
$xpath = static::newxPath(static::$manifest, static::$namespaces); |
||||
$items = $xpath->query('/imscc:manifest/imscc:organizations/imscc:organization/imscc:item | /imscc:manifest/imscc:resources/imscc:resource[@type="'.static::CC_TYPE_QUESTION_BANK.'"]'); |
||||
$this->createInstances($items); |
||||
|
||||
$resources = new Cc13Resource(); |
||||
$forums = new Cc13Forum(); |
||||
$quiz = new Cc13Quiz(); |
||||
|
||||
$documentValues = $resources->generateData('document'); |
||||
$linkValues = $resources->generateData('link'); |
||||
$forumValues = $forums->generateData(); |
||||
$quizValues = $quiz->generateData(); |
||||
|
||||
if (!empty($forums)) { |
||||
$saved = $forums->storeForums($forumValues); |
||||
} |
||||
|
||||
if (!empty($quizValues)) { |
||||
$saved = $quiz->storeQuizzes($quizValues); |
||||
} |
||||
|
||||
if (!empty($documentValues)) { |
||||
$saved = $resources->storeDocuments($documentValues, static::$pathToManifestFolder); |
||||
} |
||||
|
||||
if (!empty($linkValues)) { |
||||
$saved = $resources->storeLinks($linkValues); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,92 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
class Imscc13Import |
||||
{ |
||||
const FORMAT_IMSCC13 = 'imscc13'; |
||||
|
||||
public function log($message, $level, $a = null, $depth = null, $display = false) |
||||
{ |
||||
error_log("(imscc1) $message , level : $level , extra info: $a, message depth : $depth"); |
||||
} |
||||
|
||||
public static function detectFormat($filepath) |
||||
{ |
||||
$manifest = Cc1p3Convert::getManifest($filepath); |
||||
|
||||
if (file_exists($manifest)) { |
||||
// Looks promising, lets load some information. |
||||
$handle = fopen($manifest, 'r'); |
||||
$xmlSnippet = fread($handle, 1024); |
||||
fclose($handle); |
||||
|
||||
// Check if it has the required strings. |
||||
$xmlSnippet = strtolower($xmlSnippet); |
||||
$xmlSnippet = preg_replace('/\s*/m', '', $xmlSnippet); |
||||
$xmlSnippet = str_replace("'", '', $xmlSnippet); |
||||
$xmlSnippet = str_replace('"', '', $xmlSnippet); |
||||
|
||||
$search_string = "xmlns=http://www.imsglobal.org/xsd/imsccv1p3/imscp_v1p1"; |
||||
if (strpos($xmlSnippet, $search_string) !== false) { |
||||
return self::FORMAT_IMSCC13; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
public function execute($filepath) |
||||
{ |
||||
$manifest = Cc1p3Convert::getManifest($filepath); |
||||
|
||||
if (empty($manifest)) { |
||||
throw new RuntimeException('No Manifest detected!'); |
||||
} |
||||
|
||||
$validator = new ManifestValidator('schemas13'); |
||||
|
||||
if (!$validator->validate($manifest)) { |
||||
throw new RuntimeException('validation error(s): '.PHP_EOL.ErrorMessages::instance()); |
||||
} |
||||
|
||||
$cc113Convert = new Cc1p3Convert($manifest); |
||||
|
||||
if ($cc113Convert->isAuth()) { |
||||
throw new RuntimeException('protected_cc_not_supported'); |
||||
} |
||||
|
||||
$cc113Convert->generateImportData(); |
||||
} |
||||
|
||||
/** |
||||
* Unzip a file into the specified directory. Throws a RuntimeException |
||||
* if the extraction failed. |
||||
*/ |
||||
public static function unzip($file, $to = 'cache/zip') |
||||
{ |
||||
@ini_set('memory_limit', '256M'); |
||||
if (!is_dir($to)) { |
||||
mkdir($to); |
||||
chmod($to, 0777); |
||||
} |
||||
if (class_exists('ZipArchive')) { |
||||
// use ZipArchive |
||||
$zip = new ZipArchive(); |
||||
$res = $zip->open($file); |
||||
if ($res === true) { |
||||
$zip->extractTo($to); |
||||
$zip->close(); |
||||
} else { |
||||
throw new RuntimeException('Could not open zip file [ZipArchive].'); |
||||
} |
||||
} else { |
||||
// use PclZip |
||||
$zip = new PclZip($file); |
||||
if ($zip->extract(PCLZIP_OPT_PATH, $to) === 0) { |
||||
throw new RuntimeException('Could not extract zip file [PclZip].'); |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@ |
||||
<?xml version = "1.0" encoding = "UTF-8"?> |
||||
<xs:schema xmlns ="http://dummy.libxml2.validator" |
||||
targetNamespace ="http://dummy.libxml2.validator" |
||||
xmlns:xs ="http://www.w3.org/2001/XMLSchema" |
||||
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" |
||||
xmlns:imscp ="http://www.imsglobal.org/xsd/imsccv1p3/imscp_v1p1" |
||||
xmlns:lomimscc ="http://ltsc.ieee.org/xsd/imsccv1p3/LOM/manifest" |
||||
xmlns:lom ="http://ltsc.ieee.org/xsd/imsccv1p3/LOM/resource" |
||||
xmlns:cc ="http://www.imsglobal.org/xsd/imsccv1p3/imsccauth_v1p3" |
||||
version="IMS CC 1.3 CP 1.2" |
||||
elementFormDefault ="qualified" |
||||
attributeFormDefault="unqualified" |
||||
> |
||||
|
||||
<xs:import namespace="http://www.imsglobal.org/xsd/imsccv1p3/imscp_v1p1" schemaLocation="ccv1p3_imscp_v1p2_v1p0.xsd" /> |
||||
<!--xs:import namespace="http://ltsc.ieee.org/xsd/imsccv1p3/LOM/manifest" schemaLocation="LOM/ccv1p3_lommanifest_v1p0.xsd"/--> |
||||
<!--xs:import namespace="http://ltsc.ieee.org/xsd/imsccv1p3/LOM/resource" schemaLocation="LOM/ccv1p3_lomresource_v1p0.xsd"/--> |
||||
<!--xs:import namespace="http://www.imsglobal.org/xsd/imsccv1p3/imsccauth_v1p3" schemaLocation="ccv1p3_imsccauth_v1p3.xsd" /--> |
||||
</xs:schema> |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue