Esempio n. 1
0
        /**
         * Create the imsmanifest.xml file.
         *
         * @return False on error, true otherwise.
         * @author Thanos Kyritsis <*****@*****.**>
         * @author Amand Tihon <*****@*****.**>
         */
        function createManifest() {

            /**
             * Create a simple <metadata>
             *
             *
             * @param $title The resource title
             * @param $description The resource description
             * @return A string containing the metadata block.
             * @author Thanos Kyritsis <*****@*****.**>
             * @author Amand Tihon <*****@*****.**>
             */
            function makeMetaData($title, $description, $identifier) {
                if (empty($title) and empty($description)) {
                    return ' ';
                }

                $out = "<metadata>" . "\n"
                        . "<lom:lom>" . "\n"
                        . "<lom:general>" . "\n"
                        . "<lom:identifier>" . "\n"
                        . "<lom:entry>" . $identifier
                        . "</lom:entry>" . "\n"
                        . "</lom:identifier>" . "\n";

                if (empty($title)) {
                    $title = "null";
                }
                $out .= "<lom:title>" . "\n"
                        . "<lom:string>"
                        . htmlspecialchars($title)
                        . "</lom:string>" . "\n"
                        . "</lom:title>" . "\n";

                if (empty($description)) {
                    $description = "null";
                    $keyword = "null";
                }
                $out .= "<lom:description>" . "\n"
                        . "<lom:string>"
                        . htmlspecialchars($description)
                        . "</lom:string>" . "\n"
                        . "</lom:description>" . "\n";
                $out .= "<lom:keyword>" . "\n"
                        . "<lom:string>"
                        . htmlspecialchars($description)
                        . "</lom:string>" . "\n"
                        . "</lom:keyword>" . "\n";

                $out .= "</lom:general>" . "\n"
                        . "<lom:lifeCycle>" . "\n"
                        . "<lom:version>" . "\n"
                        . "<lom:string>1.0</lom:string>" . "\n"
                        . "</lom:version>" . "\n"
                        . "<lom:status>" . "\n"
                        . "<lom:source>LOMv1.0</lom:source>" . "\n"
                        . "<lom:value>final</lom:value>" . "\n"
                        . "</lom:status>" . "\n"
                        . "</lom:lifeCycle>" . "\n"
                        . "<lom:metaMetadata>" . "\n"
                        . "<lom:identifier>" . "\n"
                        . "<lom:entry>" . $identifier
                        . "</lom:entry>" . "\n"
                        . "</lom:identifier>" . "\n"
                        . "<lom:metadataSchema>LOMv1.0</lom:metadataSchema>" . "\n"
                        . "<lom:metadataSchema>SCORM_CAM_v1.3</lom:metadataSchema>" . "\n"
                        . "</lom:metaMetadata>" . "\n"
                        . "<lom:technical>" . "\n"
                        . "<lom:format>text/html</lom:format>" . "\n" // TODO
                        . "</lom:technical>" . "\n"
                        . "<lom:rights>" . "\n"
                        . "<lom:cost>" . "\n"
                        . "<lom:source>LOMv1.0</lom:source>" . "\n"
                        . "<lom:value>no</lom:value>" . "\n"
                        . "</lom:cost>" . "\n"
                        . "<lom:copyrightAndOtherRestrictions>" . "\n"
                        . "<lom:source>LOMv1.0</lom:source>" . "\n"
                        . "<lom:value>no</lom:value>" . "\n"
                        . "</lom:copyrightAndOtherRestrictions>" . "\n"
                        . "</lom:rights>" . "\n"
                        . "</lom:lom>" . "\n"
                        . "</metadata>" . "\n";

                return $out;
            }

            /**
             * Create a <metadata> for the whole CAM model package
             *
             *
             * @param $title The resource title
             * @param $description The resource description
             * @return A string containing the metadata block.
             *
             * @author Thanos Kyritsis <*****@*****.**>
             */
            function makeCAMetaData($title, $description) {
                if (empty($title) and empty($description)) {
                    return ' ';
                }

                $out = "<metadata>" . "\n"
                        . "<schema>ADL SCORM</schema>" . "\n"
                        . "<schemaversion>CAM 1.3</schemaversion>" . "\n"
                        . "<lom:lom>" . "\n"
                        . "<lom:general>" . "\n";

                if (empty($title)) {
                    $title = "null";
                }
                $out .= "<lom:title>" . "\n"
                        . "<lom:string>"
                        . htmlspecialchars($title)
                        . "</lom:string>" . "\n"
                        . "</lom:title>" . "\n";

                if (empty($description)) {
                    $description = "null";
                }
                $out .= "<lom:description>" . "\n"
                        . "<lom:string>"
                        . htmlspecialchars($description)
                        . "</lom:string>" . "\n"
                        . "</lom:description>" . "\n";

                $out .= "</lom:general>" . "\n"
                        . "<lom:metaMetadata>" . "\n"
                        . "<lom:metadataSchema>LOMv1.0</lom:metadataSchema>" . "\n"
                        . "<lom:metadataSchema>SCORM_CAM_v1.3</lom:metadataSchema>" . "\n"
                        . "</lom:metaMetadata>" . "\n"
                        . "</lom:lom>" . "\n"
                        . "</metadata>" . "\n";

                return $out;
            }

            /**
             * Recursive function to deal with the tree representation of the items
             *
             * @param $itemlist the subtree to build
             * @param $depth indentation level. Is it really useful ?
             * @return the (sub-)tree representation
             *
             * @author Thanos Kyritsis <*****@*****.**>
             * @author Amand Tihon <*****@*****.**>
             */
            $blocking = "";

            function createItemList($itemlist, $depth = 0) {
                global $blocking;
                $out = "";
                $ident = "";
                for ($i = 0; $i < $depth; $i++) {
                    $ident .= "    ";
                }
                foreach ($itemlist as $item) {
                    $identifier = "I_" . $item['ID'];
                    $out .= $ident . '<item identifier="' . $identifier . '" isvisible="true" ';
                    if ($item['contentType'] != 'LABEL') {
                        $out .= 'identifierref="R_' . $item['ID'] . '" ';
                    }
                    $out .= '>' . "\n";
                    $out .= $ident . '    <title>' . htmlspecialchars($item['name']) . '</title>' . "\n";

                    // Check if previous was blocking
                    // not valid for scorm 2004
                    /* if (!empty($blocking) && ($item['contentType'] != 'LABEL'))
                      {
                      $out .= '        <adlcp:prerequisites type="aicc_script"><![CDATA[I_'.$blocking.']]></adlcp:prerequisites>'."\n";
                      } */

                    // Add metadata, except for LABELS
                    if ($item['contentType'] != 'LABEL') {
                        $out .= makeMetaData($item['name'], $item['itemComment'], $identifier);
                    }

                    if (!isset($item['children'])) {
                        // change only if we do not recurse.
                        $blocking = ($item['lock'] == 'CLOSE') ? $item['ID'] : '';
                    } else {
                        $out .= createItemList($item['children'], $depth + 1);
                    }
                    $out .= $ident . '</item>' . "\n";
                }
                return $out;
            }

            /**
             * Create the frame file that'll hold the document. This frame is supposed to
             * set the SCO's status
             * @param $filename string: the name of the file to create, absolute.
             * @param $targetPath string: The actual document path, relative to the scorm
             * @return False on error, true otherwise.
             *
             * @author Thanos Kyritsis <*****@*****.**>
             * @author Amand Tihon <*****@*****.**>
             */
            function createFrameFile($fileName, $targetPath) {
                global $langErrorCreatingFrame, $langErrorCreatingManifest, $charset;

                if (!($f = fopen($fileName, 'w'))) {
                    $this->error[] = $langErrorCreatingFrame;
                    return false;
                }

                fwrite($f, '<html><head>
    <meta http-equiv="Content-Type" content="text/html; charset=' . $charset . '">
    <script src="APIWrapper.js" type="text/javascript" language="JavaScript"></script>
    <title>Default Title</title>
</head>
<frameset border="0" rows="100%" onload="immediateComplete()">
    <frame src="' . $targetPath . '" scrolling="auto">
</frameset>
</html>');
                fclose($f);

                return true;
            }

            /**
             * Create the frame file that'll hold the course description.
             * This frame sets the SCO's status
             * @param $filename string: the name of the file to create, absolute.
             * @return False on error, true otherwise.
             *
             * @author Thanos Kyritsis <*****@*****.**>
             */
            function createDescFrameFile($fileName) {
                global $langErrorCreatingFrame, $course_id, $langThisCourseDescriptionIsEmpty, $charset;

                if (!($f = fopen($fileName, 'w'))) {
                    $this->error[] = $langErrorCreatingFrame;
                    return false;
                }

                $course_description = "";
                $blocs = Database::get()->queryArray("SELECT `id`, `title`, `comments` FROM `course_description` WHERE course_id = ?d ORDER BY `order`", $course_id);
                if (count($blocs) > 0) {
                    $course_description .= "
					<hr noshade size=\"1\">";
                    foreach ($blocs as $bloc) {
                        $course_description .= "
					<H4>
						" . $bloc->title . "
					</H4>
					<font size=2 face='arial, helvetica'>
						" . make_clickable(nl2br($bloc->comments)) . "
					</font>";
                    }
                } else {
                    $course_description .= "<br><h4>$langThisCourseDescriptionIsEmpty</h4>";
                }

                fwrite($f, '<html>' . "\n"
                        . '<head>' . "\n"
                        . '<meta http-equiv="Content-Type" content="text/html; charset=' . $charset . '">' . "\n"
                        . '<script src="APIWrapper.js" type="text/javascript" language="JavaScript"></script>' . "\n"
                        . '</head>' . "\n"
                        . '<body onload="immediateComplete()">' . "\n"
                        . '<table width="99%" border="0">' . "\n"
                        . '<tr>' . "\n"
                        . '<td colspan="2">' . "\n"
                        . $course_description . "\n"
                        . '</td>' . "\n"
                        . '</tr>' . "\n"
                        . '<tr name="bottomLine">' . "\n"
                        . '<td colspan="2">' . "\n"
                        . '<br>' . "\n"
                        . '<hr noshade size="1">' . "\n"
                        . '</td>' . "\n"
                        . '</tr>' . "\n"
                        . '</table>' . "\n"
                        . '</body>' . "\n"
                        . '</html>' . "\n"
                );
                fclose($f);

                return true;
            }

            // Start creating sections for items and resources
            // First the items...
            $manifest_itemTree = '<organizations default="A1"><organization identifier="A1">' . "\n"
                    . '<title>' . $this->name . '</title>' . "\n"
                    . createItemList($this->itemTree)
                    . '</organization></organizations>' . "\n";

            // ...Then the resources

            $manifest_resources = "<resources>\n";
            foreach ($this->resourceMap as $module) {
                if ($module['contentType'] == 'LABEL') {
                    continue;
                }

                switch ($module['contentType']) {
                    case 'DOCUMENT':
                    case 'MEDIA':
                        $framefile = $this->destDir . '/frame_for_' . $module['ID'] . '.html';
                        $targetfile = 'Documents' . $module['path'];

                        // Create an html file with a frame for the document.
                        if (!createFrameFile($framefile, $targetfile)) {
                            return false;
                        }

                        // Add the resource to the manifest
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent"  adlcp:scormType="sco" '
                                . ' href="' . basename($framefile) . '">' . "\n"
                                . '  <file href="' . basename($framefile) . '" />' . "\n"
                                . '  <file href="' . $targetfile . '">' . "\n"
                                . makeMetaData($module['name'], $module['resourceComment'], $ridentifier)
                                . "</file>\n"
                                . "</resource>\n";
                        break;

                    case 'EXERCISE':
                        $targetfile = $module['fileName'];

                        // Add the resource to the manifest
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent"  adlcp:scormType="sco" '
                                . ' href="' . $targetfile . '" >' . "\n"
                                . '  <file href="' . $targetfile . '">' . "\n"
                                . makeMetaData($module['name'], $module['resourceComment'], $ridentifier)
                                . "</file>\n"
                                . "</resource>\n";
                        break;

                    case 'SCORM_ASSET' :
                        // Add the resource to the manifest
                        $path = 'OrigScorm';
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent" '
                                . ' href="OrigScorm' . $module['path'] . '">' . "\n"
                                . '  <file href="OrigScorm' . $module['path'] . '">' . "\n"
                                . makeMetaData($module['name'], $module['resourceComment'], $ridentifier)
                                . "</file>\n"
                                . "</resource>\n";
                        break;

                    case 'SCORM' :
                        // Add the resource to the manifest
                        $path = 'OrigScorm';
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent"  adlcp:scormType="sco" '
                                . ' href="OrigScorm' . $module['path'] . '">' . "\n"
                                . '  <file href="OrigScorm' . $module['path'] . '">' . "\n"
                                . makeMetaData($module['name'], $module['resourceComment'], $ridentifier)
                                . "</file>\n"
                                . "</resource>\n";
                        break;

                    case 'COURSE_DESCRIPTION':
                        $framefile = $this->destDir . '/frame_for_' . $module['ID'] . '.html';

                        // Create an html file with a frame for the document.
                        if (!createDescFrameFile($framefile)) {
                            return false;
                        }

                        // Add the resource to the manifest
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent"  adlcp:scormType="sco" '
                                . ' href="' . basename($framefile) . '">' . "\n"
                                . '  <file href="' . basename($framefile) . '">' . "\n"
                                . makeMetaData($module['name'], $module['resourceComment'], $ridentifier)
                                . "</file>\n"
                                . "</resource>\n";

                        break;

                    case 'LINK':
                    case 'MEDIALINK':
                        $framefile = $this->destDir . '/frame_for_' . $module['ID'] . '.html';
                        if ($module['contentType'] == 'MEDIALINK') {
                            $targetfile = urldecode(MultimediaHelper::makeEmbeddableMedialink($module['path']));
                        } else {
                            $targetfile = $module['path'];
                        }

                        // Create an html file with a frame for the document.
                        if (!createFrameFile($framefile, $targetfile)) {
                            return false;
                        }

                        // Add the resource to the manifest
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent"  adlcp:scormType="sco" '
                                . ' href="' . basename($framefile) . '">' . "\n"
                                . '  <file href="' . basename($framefile) . '">' . "\n"
                                . makeMetaData($module['name'], $module['resourceComment'], $ridentifier)
                                . "</file>\n"
                                . "</resource>\n";
                        break;

                    default : break;
                }
            }
            $manifest_resources .= '</resources>' . "\n";

            $manifestPath = $this->destDir . '/imsmanifest.xml';
            if (!$f = fopen($manifestPath, 'w')) {
                $this->error[] = $GLOBALS['langErrorCreatingManifest'];
                return false;
            }

            // Prepare Metadata
            $metadata = makeCAMetaData($this->name, $this->comment);

            // Write header
            global $charset;
            fwrite($f, '<?xml version="1.0" encoding="' . $charset . '" ?>
<manifest identifier="SingleCourseManifest" version="1.1"
          xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"
          xmlns:lom="http://ltsc.ieee.org/xsd/LOM"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_v1p3"
          xmlns:imsss="http://www.imsglobal.org/xsd/imsss"
          xmlns:adlseq="http://www.adlnet.org/xsd/adlseq_v1p3"
          xmlns:adlnav="http://www.adlnet.org/xsd/adlnav_v1p3"
          xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd
          http://ltsc.ieee.org/xsd/LOM lom.xsd
          http://www.adlnet.org/xsd/adlcp_v1p3 adlcp_v1p3.xsd
          http://www.imsglobal.org/xsd/imsss imsss_v1p0.xsd
          http://www.adlnet.org/xsd/adlseq_v1p3 adlseq_v1p3.xsd
          http://www.adlnet.org/xsd/adlnav_v1p3 adlnav_v1p3.xsd">' . "\n");
            fwrite($f, $metadata);
            fwrite($f, $manifest_itemTree);
            fwrite($f, $manifest_resources);
            fwrite($f, "</manifest>\n");
            fclose($f);

            return true;
        }
Esempio n. 2
0
        /**
         * Create the imsmanifest.xml file.
         *
         * @return False on error, true otherwise.
         * @author Thanos Kyritsis <*****@*****.**>
         * @author Amand Tihon <*****@*****.**>
         */
        function createManifest()
        {
            /**
             * Create a <metadata> for the whole CAM model package
             *
             *
             * @param $title The resource title
             * @param $description The resource description
             * @param $language The resource language (required in IMS CP 1.1.4). Defaults to "en"
             * @return A string containing the metadata block.
             *
             * @author Sakis Agorastos <*****@*****.**>
             * @author Thanos Kyritsis <*****@*****.**>
             */
            function makeCAMetaData($title, $description, $language)
            {
                if (empty($language)) {
                    $language = "en";
                }
                if (empty($title) and empty($description)) {
                    return ' ';
                }
                $out = "<metadata>" . "\n" . "<schema>IMS Content</schema>" . "\n" . "<schemaversion>1.1.4</schemaversion>" . "\n" . "<imsmd:lom>" . "\n" . "<imsmd:general>" . "\n";
                if (empty($title)) {
                    $title = "null";
                }
                $out .= "<imsmd:title>" . "\n" . "<imsmd:langstring xml:lang=\"" . $language . "\">" . htmlspecialchars($title) . "</imsmd:langstring>" . "\n" . "</imsmd:title>" . "\n";
                $out .= "<imsmd:language>" . $language . "</imsmd:language>" . "\n";
                if (empty($description)) {
                    $description = "null";
                }
                $out .= "<imsmd:description>" . "\n" . "<imsmd:langstring xml:lang=\"" . $language . "\">" . htmlspecialchars($description) . "</imsmd:langstring>" . "\n" . "</imsmd:description>" . "\n";
                $out .= "<imsmd:structure>" . "\n" . "<imsmd:source>" . "\n" . "<imsmd:langstring xml:lang=\"x-none\">LOMv1.0</imsmd:langstring>" . "\n" . "</imsmd:source>" . "\n" . "<imsmd:value>" . "\n" . "<imsmd:langstring xml:lang=\"x-none\">Hierarchical</imsmd:langstring>" . "\n" . "</imsmd:value>" . "\n" . "</imsmd:structure>";
                $out .= "</imsmd:general>" . "\n" . "</imsmd:lom>" . "\n" . "</metadata>" . "\n";
                return $out;
            }
            /**
             * Recursive function to deal with the tree representation of the items
             *
             * @param $itemlist the subtree to build
             * @param $depth indentation level. Is it really useful ?
             * @return the (sub-)tree representation
             *
             * @author Thanos Kyritsis <*****@*****.**>
             * @author Amand Tihon <*****@*****.**>
             */
            $blocking = "";
            function createItemList($itemlist, $depth = 0)
            {
                global $blocking;
                $out = "";
                $ident = "";
                for ($i = 0; $i < $depth; $i++) {
                    $ident .= "    ";
                }
                foreach ($itemlist as $item) {
                    $identifier = "I_" . $item['ID'];
                    $out .= $ident . '<item identifier="' . $identifier . '" isvisible="true" ';
                    if ($item['contentType'] != 'LABEL') {
                        $out .= 'identifierref="R_' . $item['ID'] . '" ';
                    }
                    $out .= '>' . "\n";
                    $out .= $ident . '    <title>' . htmlspecialchars($item['name']) . '</title>' . "\n";
                    if (!isset($item['children'])) {
                        // change only if we do not recurse.
                        $blocking = $item['lock'] == 'CLOSE' ? $item['ID'] : '';
                    } else {
                        $out .= createItemList($item['children'], $depth + 1);
                    }
                    $out .= $ident . '</item>' . "\n";
                }
                return $out;
            }
            /**
             * Create the frame file that'll hold the document. This frame is supposed to
             * set the SCO's status
             * @param $filename string: the name of the file to create, absolute.
             * @param $targetPath string: The actual document path, relative to the scorm
             * @return False on error, true otherwise.
             *
             * @author Thanos Kyritsis <*****@*****.**>
             * @author Amand Tihon <*****@*****.**>
             */
            function createFrameFile($fileName, $targetPath)
            {
                global $langErrorCreatingFrame, $langErrorCreatingManifest, $charset;
                if (!($f = fopen($fileName, 'w'))) {
                    $this->error[] = $langErrorCreatingFrame;
                    return false;
                }
                fwrite($f, '<html><head>
    <meta http-equiv="Content-Type" content="text/html; charset=' . $charset . '">
    <script src="APIWrapper.js" type="text/javascript" language="JavaScript"></script>
    <title>Default Title</title>
</head>
<frameset border="0" rows="100%" onload="immediateComplete()">
    <frame src="' . $targetPath . '" scrolling="auto">
</frameset>
</html>');
                fclose($f);
                return true;
            }
            /**
             * Create the frame file that'll hold the course description.
             * This frame sets the SCO's status
             * @param $filename string: the name of the file to create, absolute.
             * @return False on error, true otherwise.
             *
             * @author Thanos Kyritsis <*****@*****.**>
             */
            function createDescFrameFile($fileName)
            {
                global $langErrorCreatingFrame, $course_id, $langThisCourseDescriptionIsEmpty, $charset;
                if (!($f = fopen($fileName, 'w'))) {
                    $this->error[] = $langErrorCreatingFrame;
                    return false;
                }
                $course_description = "";
                $blocs = Database::get()->queryArray("SELECT `id`, `title`, `comments` FROM `course_description` WHERE course_id = ?d ORDER BY id", $course_id);
                if (count($blocs) > 0) {
                    $course_description .= "\n                            <hr noshade size=\"1\">";
                    foreach ($blocs as $bloc) {
                        $course_description .= "\n                            <H4>\n                                    " . $bloc->title . "\n                            </H4>\n                            <font size=2 face='arial, helvetica'>\n                                    " . make_clickable(nl2br($bloc->comments)) . "\n                            </font>";
                    }
                } else {
                    $course_description .= "<br><h4>{$langThisCourseDescriptionIsEmpty}</h4>";
                }
                fwrite($f, '<html>' . "\n" . '<head>' . "\n" . '<meta http-equiv="Content-Type" content="text/html; charset=' . $charset . '">' . "\n" . '<script src="APIWrapper.js" type="text/javascript" language="JavaScript"></script>' . "\n" . '</head>' . "\n" . '<body onload="immediateComplete()">' . "\n" . '<table width="99%" border="0">' . "\n" . '<tr>' . "\n" . '<td colspan="2">' . "\n" . $course_description . "\n" . '</td>' . "\n" . '</tr>' . "\n" . '<tr name="bottomLine">' . "\n" . '<td colspan="2">' . "\n" . '<br>' . "\n" . '<hr noshade size="1">' . "\n" . '</td>' . "\n" . '</tr>' . "\n" . '</table>' . "\n" . '</body>' . "\n" . '</html>' . "\n");
                fclose($f);
                return true;
            }
            // Start creating sections for items and resources
            // First the items...
            $manifest_itemTree = '<organizations default="A1">' . '<organization identifier="A1" structure = "hierarchical">' . '<title>' . $this->name . '</title>' . createItemList($this->itemTree) . '</organization>' . "" . '</organizations>' . "";
            // ...Then the resources
            $manifest_resources = "<resources>\n";
            foreach ($this->resourceMap as $module) {
                if ($module['contentType'] == 'LABEL') {
                    continue;
                }
                switch ($module['contentType']) {
                    case 'DOCUMENT':
                    case 'MEDIA':
                        $framefile = $this->destDir . '/frame_for_' . $module['ID'] . '.html';
                        $targetfile = 'Documents' . $module['path'];
                        // Create an html file with a frame for the document.
                        if (!createFrameFile($framefile, $targetfile)) {
                            return false;
                        }
                        // Add the resource to the manifest
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent" ' . ' href="' . basename($framefile) . '">' . "\n" . '  <file href="' . basename($framefile) . '" />' . "\n" . '  <file href="' . $targetfile . '">' . "\n" . "</file>\n" . "</resource>\n";
                        break;
                    case 'EXERCISE':
                        $targetfile = $module['fileName'];
                        // Add the resource to the manifest
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent"  ' . ' href="' . $targetfile . '" >' . "\n" . '  <file href="' . $targetfile . '">' . "\n" . "</file>\n" . "</resource>\n";
                        break;
                    case 'SCORM_ASSET':
                        // Add the resource to the manifest
                        $path = 'OrigScorm';
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent" ' . ' href="OrigScorm' . $module['path'] . '">' . "\n" . '  <file href="OrigScorm' . $module['path'] . '">' . "\n" . "</file>\n" . "</resource>\n";
                        break;
                    case 'SCORM':
                        // Add the resource to the manifest
                        $path = 'OrigScorm';
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent"  ' . ' href="OrigScorm' . $module['path'] . '">' . "\n" . '  <file href="OrigScorm' . $module['path'] . '">' . "\n" . "</file>\n" . "</resource>\n";
                        break;
                    case 'COURSE_DESCRIPTION':
                        $framefile = $this->destDir . '/frame_for_' . $module['ID'] . '.html';
                        // Create an html file with a frame for the document.
                        if (!createDescFrameFile($framefile)) {
                            return false;
                        }
                        // Add the resource to the manifest
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent" ' . ' href="' . basename($framefile) . '">' . "\n" . '  <file href="' . basename($framefile) . '">' . "\n" . "</file>\n" . "</resource>\n";
                        break;
                    case 'LINK':
                    case 'MEDIALINK':
                        $framefile = $this->destDir . '/frame_for_' . $module['ID'] . '.html';
                        $targetfile = $module['path'];
                        // Create an html file with a frame for the document.
                        if (!createFrameFile($framefile, $targetfile)) {
                            return false;
                        }
                        // Add the resource to the manifest
                        $ridentifier = "R_" . $module['ID'];
                        $manifest_resources .= '<resource identifier="' . $ridentifier . '" type="webcontent"  ' . ' href="' . basename($framefile) . '">' . "\n" . '  <file href="' . basename($framefile) . '" />' . "\n" . "</resource>\n";
                        break;
                    default:
                        break;
                }
            }
            $manifest_resources .= '</resources>' . "\n";
            $manifestPath = $this->destDir . '/imsmanifest.xml';
            if (!($f = fopen($manifestPath, 'w'))) {
                $this->error[] = $GLOBALS['langErrorCreatingManifest'];
                return false;
            }
            // Prepare Metadata
            $metadata = makeCAMetaData($this->name, $this->comment, $this->language);
            // Write header
            fwrite($f, '<?xml version = "1.0" encoding = "UTF-8"?>
                    <manifest xmlns = "http://www.imsglobal.org/xsd/imscp_v1p1" 
                    	xmlns:imsmd = "http://www.imsglobal.org/xsd/imsmd_v1p2" 
                    	xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 	
                        xsi:schemaLocation = "http://www.imsglobal.org/xsd/imscp_v1p1 http://www.imsglobal.org/xsd/imscp_v1p1.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 http://www.imsglobal.org/xsd/imsmd_v1p2.xsd "
                    	identifier="Manifest1"
                       	version="IMS CP 1.1.4">' . "\n");
            fwrite($f, $metadata);
            fwrite($f, $manifest_itemTree);
            fwrite($f, $manifest_resources);
            fwrite($f, "</manifest>\n");
            fclose($f);
            return true;
        }