. /** * Private imscp module utility functions * * @package mod * @subpackage imscp * @copyright 2009 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once("$CFG->dirroot/mod/imscp/lib.php"); require_once("$CFG->libdir/filelib.php"); require_once("$CFG->libdir/resourcelib.php"); function imscp_print_content($imscp, $cm, $course) { global $PAGE, $CFG; $items = unserialize($imscp->structure); $first = reset($items); $context = get_context_instance(CONTEXT_MODULE, $cm->id); $urlbase = "$CFG->wwwroot/pluginfile.php"; $path = '/'.$context->id.'/mod_imscp/content/'.$imscp->revision.'/'.$first['href']; $firsturl = file_encode_url($urlbase, $path, false); echo '
'; echo '
'; echo '
    '; foreach ($items as $item) { echo imscp_htmllize_item($item, $imscp, $cm); } echo '
'; echo ''; echo '
'; echo '
'; $PAGE->requires->js_init_call('M.mod_imscp.init'); return; } /** * Internal function - creates htmls structure suitable for YUI tree. */ function imscp_htmllize_item($item, $imscp, $cm) { global $CFG; $context = get_context_instance(CONTEXT_MODULE, $cm->id); $urlbase = "$CFG->wwwroot/pluginfile.php"; $path = '/'.$context->id.'/mod_imscp/content/'.$imscp->revision.'/'.$item['href']; $url = file_encode_url($urlbase, $path, false); $result = "
  • ".$item['title'].''; if ($item['subitems']) { $result .= ''; } $result .= '
  • '; return $result; } /** * Parse an IMS content package's manifest file to determine its structure * @param object $imscp * @param object $context * @return array */ function imscp_parse_structure($imscp, $context) { $fs = get_file_storage(); if (!$manifestfile = $fs->get_file($context->id, 'mod_imscp', 'content', $imscp->revision, '/', 'imsmanifest.xml')) { return null; } return imscp_parse_manifestfile($manifestfile->get_content()); } /** * Parse the contents of a IMS package's manifest file * @param string $manifestfilecontents the contents of the manifest file * @return array */ function imscp_parse_manifestfile($manifestfilecontents) { $doc = new DOMDocument(); if (!$doc->loadXML($manifestfilecontents, LIBXML_NONET)) { return null; } // we put this fake URL as base in order to detect path changes caused by xml:base attributes $doc->documentURI = 'http://grrr/'; $xmlorganizations = $doc->getElementsByTagName('organizations'); if (empty($xmlorganizations->length)) { return null; } $default = null; if ($xmlorganizations->item(0)->attributes->getNamedItem('default')) { $default = $xmlorganizations->item(0)->attributes->getNamedItem('default')->nodeValue; } $xmlorganization = $doc->getElementsByTagName('organization'); if (empty($xmlorganization->length)) { return null; } $organization = null; foreach ($xmlorganization as $org) { if (is_null($organization)) { // use first if default nor found $organization = $org; } if (!$org->attributes->getNamedItem('identifier')) { continue; } if ($default === $org->attributes->getNamedItem('identifier')->nodeValue) { // found default - use it $organization = $org; break; } } // load all resources $resources = array(); $xmlresources = $doc->getElementsByTagName('resource'); foreach ($xmlresources as $res) { if (!$identifier = $res->attributes->getNamedItem('identifier')) { continue; } $identifier = $identifier->nodeValue; if ($xmlbase = $res->baseURI) { // undo the fake URL, we are interested in relative links only $xmlbase = str_replace('http://grrr/', '/', $xmlbase); $xmlbase = rtrim($xmlbase, '/').'/'; } else { $xmlbase = ''; } if (!$href = $res->attributes->getNamedItem('href')) { // If href not found look for $fileresources = $res->getElementsByTagName('file'); foreach ($fileresources as $file) { $href = $file->getAttribute('href'); } if (empty($href)) { continue; } } else { $href = $href->nodeValue; } if (strpos($href, 'http://') !== 0) { $href = $xmlbase.$href; } // href cleanup - Some packages are poorly done and use \ in urls $href = ltrim(strtr($href, "\\", '/'), '/'); $resources[$identifier] = $href; } $items = array(); foreach ($organization->childNodes as $child) { if ($child->nodeName === 'item') { if (!$item = imscp_recursive_item($child, 0, $resources)) { continue; } $items[] = $item; } } return $items; } function imscp_recursive_item($xmlitem, $level, $resources) { $identifierref = ''; if ($identifierref = $xmlitem->attributes->getNamedItem('identifierref')) { $identifierref = $identifierref->nodeValue; } $title = '?'; $subitems = array(); foreach ($xmlitem->childNodes as $child) { if ($child->nodeName === 'title') { $title = $child->textContent; } else if ($child->nodeName === 'item') { if ($subitem = imscp_recursive_item($child, $level+1, $resources)) { $subitems[] = $subitem; } } } return array('href' => isset($resources[$identifierref]) ? $resources[$identifierref] : '', 'title' => $title, 'level' => $level, 'subitems' => $subitems, ); } /** * File browsing support class */ class imscp_file_info extends file_info { protected $course; protected $cm; protected $areas; protected $filearea; public function __construct($browser, $course, $cm, $context, $areas, $filearea) { parent::__construct($browser, $context); $this->course = $course; $this->cm = $cm; $this->areas = $areas; $this->filearea = $filearea; } /** * Returns list of standard virtual file/directory identification. * The difference from stored_file parameters is that null values * are allowed in all fields * @return array with keys contextid, filearea, itemid, filepath and filename */ public function get_params() { return array('contextid'=>$this->context->id, 'component'=>'mod_imscp', 'filearea' =>$this->filearea, 'itemid' =>null, 'filepath' =>null, 'filename' =>null); } /** * Returns localised visible name. * @return string */ public function get_visible_name() { return $this->areas[$this->filearea]; } /** * Can I add new files or directories? * @return bool */ public function is_writable() { return false; } /** * Is directory? * @return bool */ public function is_directory() { return true; } /** * Returns list of children. * @return array of file_info instances */ public function get_children() { global $DB; $children = array(); $itemids = $DB->get_records('files', array('contextid'=>$this->context->id, 'component'=>'mod_imscp', 'filearea'=>$this->filearea), 'itemid', "DISTINCT itemid"); foreach ($itemids as $itemid=>$unused) { if ($child = $this->browser->get_file_info($this->context, 'mod_imscp', $this->filearea, $itemid)) { $children[] = $child; } } return $children; } /** * Returns parent file_info instance * @return file_info or null for root */ public function get_parent() { return $this->browser->get_file_info($this->context); } }