diff --git a/main/newscorm/learnpath.class.php b/main/newscorm/learnpath.class.php index 9d8a4ca28d..ba065dcaeb 100755 --- a/main/newscorm/learnpath.class.php +++ b/main/newscorm/learnpath.class.php @@ -3322,10 +3322,7 @@ class learnpath } } } - //}else{ - //prerequisites did not match - //$file = 'blank.php'; - //} + // We want to use parameters if they were defined in the imsmanifest if (strpos($file, 'blank.php') === false) { $file .= (strstr($file, '?') === false ? '?' : '') . $lp_item_params; @@ -8288,8 +8285,7 @@ class learnpath */ public function scorm_export() { - global $_course; - + $_course = api_get_course_info(); $course_id = api_get_course_int_id(); // Remove memory and time limits as much as possible as this might be a long process... @@ -8309,9 +8305,9 @@ class learnpath $root_path = $main_path = api_get_path(SYS_PATH); $files_cleanup = array(); - // Place to temporarily stash the zipfiles. + // Place to temporarily stash the zip file. // create the temp dir if it doesn't exist - // or do a cleanup befor creating the zipfile. + // or do a cleanup before creating the zip file. if (!is_dir($temp_zip_dir)) { mkdir($temp_zip_dir, api_get_permissions_for_new_directories()); } else { @@ -8332,10 +8328,13 @@ class learnpath mkdir($dest_path_to_scorm_folder, api_get_permissions_for_new_directories(), true); $zip_files_dist = copyr($current_course_path.'/scorm/'.$this->path, $dest_path_to_scorm_folder, array('imsmanifest'), $zip_files); } - // Build a dummy imsmanifest structure. Do not add to the zip yet (we still need it). + + // Build a dummy imsmanifest structure. + // Do not add to the zip yet (we still need it). // This structure is developed following regulations for SCORM 1.2 packaging in the SCORM 1.2 Content - // Aggregation Model official document, secion "2.3 Content Packaging". - $xmldoc = new DOMDocument('1.0'); // We are going to build a UTF-8 encoded manifest. Later we will recode it to the desired (and supported) encoding. + // Aggregation Model official document, section "2.3 Content Packaging". + // We are going to build a UTF-8 encoded manifest. Later we will recode it to the desired (and supported) encoding. + $xmldoc = new DOMDocument('1.0'); $root = $xmldoc->createElement('manifest'); $root->setAttribute('identifier', 'SingleCourseManifest'); $root->setAttribute('version', '1.1'); @@ -8352,7 +8351,6 @@ class learnpath $root->appendChild($metadata); $organizations = $xmldoc->createElement('organizations'); - $resources = $xmldoc->createElement('resources'); // Build the only organization we will use in building our learnpaths. @@ -8387,14 +8385,18 @@ class learnpath // For each element, add it to the imsmanifest structure, then add it to the zip. // Always call the learnpathItem->scorm_export() method to change it to the SCORM format. $link_updates = array(); - + $links_to_create = array(); foreach ($this->items as $index => $item) { if (!in_array($item->type, array(TOOL_QUIZ, TOOL_FORUM, TOOL_THREAD, TOOL_LINK, TOOL_STUDENTPUBLICATION))) { // Get included documents from this item. - if ($item->type == 'sco') - $inc_docs = $item->get_resources_from_source(null, api_get_path(SYS_COURSE_PATH).api_get_course_path().'/'.'scorm/'.$this->path.'/'.$item->get_path()); - else + if ($item->type == 'sco') { + $inc_docs = $item->get_resources_from_source( + null, + api_get_path(SYS_COURSE_PATH) . api_get_course_path() . '/' . 'scorm/' . $this->path . '/' . $item->get_path() + ); + } else { $inc_docs = $item->get_resources_from_source(); + } // Give a child element to the element. $my_item_id = $item->get_id(); $my_item = $xmldoc->createElement('item'); @@ -8445,12 +8447,11 @@ class learnpath $my_xml_file_path = str_replace($path_to_remove, '', $my_file_path); } } else { - $my_xml_file_path = $my_file_path; + $my_xml_file_path = $my_file_path; } $my_sub_dir = dirname($my_file_path); $my_sub_dir = str_replace('\\', '/', $my_sub_dir); - //$my_xml_sub_dir = api_htmlentities(api_utf8_encode($my_sub_dir), ENT_QUOTES, 'UTF-8'); $my_xml_sub_dir = $my_sub_dir; // Give a child to the element $my_resource = $xmldoc->createElement('resource'); @@ -8608,8 +8609,10 @@ class learnpath } } break; - case 'rel': // Path relative to the current document. Save xml:base as current document's directory and save file in zip as subdir.file_path - if (substr($doc_info[0], 0, 2) == '..') { + case 'rel': + // Path relative to the current document. + // Save xml:base as current document's directory and save file in zip as subdir.file_path + if (substr($doc_info[0], 0, 2) == '..') { // Relative path going up. $current_dir = dirname($current_course_path.'/'.$item->get_file_path()).'/'; $current_dir = str_replace('\\', '/', $current_dir); @@ -8627,16 +8630,16 @@ class learnpath $my_dep_file->setAttribute('href', 'document/'.$file_path); $my_dep->setAttribute('xml:base', ''); } - } else { + } else { $zip_files[] = $my_sub_dir.'/'.$doc_info[0]; $my_dep_file->setAttribute('href', $doc_info[0]); $my_dep->setAttribute('xml:base', $my_xml_sub_dir); - } - break; - default: - $my_dep_file->setAttribute('href', $doc_info[0]); - $my_dep->setAttribute('xml:base', ''); - break; + } + break; + default: + $my_dep_file->setAttribute('href', $doc_info[0]); + $my_dep->setAttribute('xml:base', ''); + break; } } $my_dep->appendChild($my_dep_file); @@ -8646,59 +8649,130 @@ class learnpath $my_resource->appendChild($dependency); $i++; } - //$my_dependency = $xmldoc->createElement('dependency'); - //$my_dependency->setAttribute('identifierref', ''); $resources->appendChild($my_resource); $zip_files[] = $my_file_path; - - //error_log('File '.$my_file_path. ' added to $zip_files', 0); } else { + // If the item is a quiz or a link or whatever non-exportable, we include a step indicating it. switch ($item->type) { case TOOL_LINK: - $my_item = $xmldoc->createElement('item'); - $my_item->setAttribute('identifier', 'ITEM_'.$item->get_id()); - $my_item->setAttribute('identifierref', 'RESOURCE_'.$item->get_id()); - $my_item->setAttribute('isvisible', 'true'); - // Give a child element to the <item> element. - $my_title = $xmldoc->createElement('title', htmlspecialchars(api_utf8_encode($item->get_title()), ENT_QUOTES, 'UTF-8')); - $my_item->appendChild($my_title); - // Give a child element <adlcp:prerequisites> to the <item> element. - $my_prereqs = $xmldoc->createElement('adlcp:prerequisites', $item->get_prereq_string()); - $my_prereqs->setAttribute('type', 'aicc_script'); - $my_item->appendChild($my_prereqs); - // Give a child element <adlcp:maxtimeallowed> to the <item> element - not yet supported. - //$xmldoc->createElement('adlcp:maxtimeallowed', ''); - // Give a child element <adlcp:timelimitaction> to the <item> element - not yet supported. - //$xmldoc->createElement('adlcp:timelimitaction', ''); - // Give a child element <adlcp:datafromlms> to the <item> element - not yet supported. - //$xmldoc->createElement('adlcp:datafromlms', ''); - // Give a child element <adlcp:masteryscore> to the <item> element. - $my_masteryscore = $xmldoc->createElement('adlcp:masteryscore', $item->get_mastery_score()); - $my_item->appendChild($my_masteryscore); - - // Attach this item to the organization element or its parent if there is one. - if (!empty($item->parent) && $item->parent != 0) { - $children = $organization->childNodes; - for ($i = 0; $i < $children->length; $i++) { - $item_temp = $children->item($i); - if ($item_temp -> nodeName == 'item') { - if ($item_temp->getAttribute('identifier') == 'ITEM_'.$item->parent) { - $item_temp -> appendChild($my_item); + $my_item = $xmldoc->createElement('item'); + $my_item->setAttribute('identifier', 'ITEM_'.$item->get_id()); + $my_item->setAttribute('identifierref', 'RESOURCE_'.$item->get_id()); + $my_item->setAttribute('isvisible', 'true'); + // Give a child element <title> to the <item> element. + $my_title = $xmldoc->createElement('title', htmlspecialchars(api_utf8_encode($item->get_title()), ENT_QUOTES, 'UTF-8')); + $my_item->appendChild($my_title); + // Give a child element <adlcp:prerequisites> to the <item> element. + $my_prereqs = $xmldoc->createElement('adlcp:prerequisites', $item->get_prereq_string()); + $my_prereqs->setAttribute('type', 'aicc_script'); + $my_item->appendChild($my_prereqs); + // Give a child element <adlcp:maxtimeallowed> to the <item> element - not yet supported. + //$xmldoc->createElement('adlcp:maxtimeallowed', ''); + // Give a child element <adlcp:timelimitaction> to the <item> element - not yet supported. + //$xmldoc->createElement('adlcp:timelimitaction', ''); + // Give a child element <adlcp:datafromlms> to the <item> element - not yet supported. + //$xmldoc->createElement('adlcp:datafromlms', ''); + // Give a child element <adlcp:masteryscore> to the <item> element. + $my_masteryscore = $xmldoc->createElement('adlcp:masteryscore', $item->get_mastery_score()); + $my_item->appendChild($my_masteryscore); + + // Attach this item to the organization element or its parent if there is one. + if (!empty($item->parent) && $item->parent != 0) { + $children = $organization->childNodes; + for ($i = 0; $i < $children->length; $i++) { + $item_temp = $children->item($i); + if ($item_temp -> nodeName == 'item') { + if ($item_temp->getAttribute('identifier') == 'ITEM_'.$item->parent) { + $item_temp -> appendChild($my_item); + } } } + } else { + $organization->appendChild($my_item); + } + + $my_file_path = 'link_'.$item->get_id().'.html'; + $sql = 'SELECT url, title FROM '.Database :: get_course_table(TABLE_LINK).' + WHERE c_id = '.$course_id.' AND id='.$item->path; + $rs = Database::query($sql); + if ($link = Database :: fetch_array($rs)) { + $url = $link['url']; + $title = stripslashes($link['title']); + $links_to_create[$my_file_path] = array('title' => $title, 'url' => $url); + //$my_xml_file_path = api_htmlentities(api_utf8_encode($my_file_path), ENT_QUOTES, 'UTF-8'); + $my_xml_file_path = $my_file_path; + $my_sub_dir = dirname($my_file_path); + $my_sub_dir = str_replace('\\', '/', $my_sub_dir); + //$my_xml_sub_dir = api_htmlentities(api_utf8_encode($my_sub_dir), ENT_QUOTES, 'UTF-8'); + $my_xml_sub_dir = $my_sub_dir; + // Give a <resource> child to the <resources> element. + $my_resource = $xmldoc->createElement('resource'); + $my_resource->setAttribute('identifier', 'RESOURCE_'.$item->get_id()); + $my_resource->setAttribute('type', 'webcontent'); + $my_resource->setAttribute('href', $my_xml_file_path); + // adlcp:scormtype can be either 'sco' or 'asset'. + $my_resource->setAttribute('adlcp:scormtype', 'asset'); + // xml:base is the base directory to find the files declared in this resource. + $my_resource->setAttribute('xml:base', ''); + // give a <file> child to the <resource> element. + $my_file = $xmldoc->createElement('file'); + $my_file->setAttribute('href', $my_xml_file_path); + $my_resource->appendChild($my_file); + $resources->appendChild($my_resource); + } + break; + case TOOL_QUIZ: + require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.class.php'; + $exe_id = $item->path; // Should be using ref when everything will be cleaned up in this regard. + $exe = new Exercise(); + $exe->read($exe_id); + $my_item = $xmldoc->createElement('item'); + $my_item->setAttribute('identifier', 'ITEM_'.$item->get_id()); + $my_item->setAttribute('identifierref', 'RESOURCE_'.$item->get_id()); + $my_item->setAttribute('isvisible', 'true'); + // Give a child element <title> to the <item> element. + $my_title = $xmldoc->createElement('title', htmlspecialchars(api_utf8_encode($item->get_title()), ENT_QUOTES, 'UTF-8')); + $my_item->appendChild($my_title); + $my_max_score = $xmldoc->createElement('max_score', $item->get_max()); + //$my_item->appendChild($my_max_score); + // Give a child element <adlcp:prerequisites> to the <item> element. + $my_prereqs = $xmldoc->createElement('adlcp:prerequisites', $item->get_prereq_string()); + $my_prereqs->setAttribute('type','aicc_script'); + $my_item->appendChild($my_prereqs); + // Give a child element <adlcp:masteryscore> to the <item> element. + $my_masteryscore = $xmldoc->createElement('adlcp:masteryscore', $item->get_mastery_score()); + $my_item->appendChild($my_masteryscore); + + // Attach this item to the organization element or hits parent if there is one. + if (!empty($item->parent) && $item->parent != 0) { + $children = $organization->childNodes; + for ($i = 0; $i < $children->length; $i++) { + $item_temp = $children->item($i); + if ($item_temp -> nodeName == 'item') { + if ($item_temp->getAttribute('identifier') == 'ITEM_'.$item->parent) { + $item_temp -> appendChild($my_item); + } + } + } + } else { + $organization->appendChild($my_item); } - } else { - $organization->appendChild($my_item); - } - $my_file_path = 'link_'.$item->get_id().'.html'; - $sql = 'SELECT url, title FROM '.Database :: get_course_table(TABLE_LINK).' WHERE c_id = '.$course_id.' AND id='.$item->path; - $rs = Database::query($sql); - if ($link = Database :: fetch_array($rs)) { - $url = $link['url']; - $title = stripslashes($link['title']); - $links_to_create[$my_file_path] = array('title' => $title, 'url' => $url); + // Include export scripts. + require_once api_get_path(SYS_CODE_PATH).'exercice/export/scorm/scorm_export.php'; + + // Get the path of the file(s) from the course directory root + //$my_file_path = $item->get_file_path('scorm/'.$this->path.'/'); + $my_file_path = 'quiz_'.$item->get_id().'.html'; + // Write the contents of the exported exercise into a (big) html file + // to later pack it into the exported SCORM. The file will be removed afterwards. + $contents = export_exercise($exe_id, true); + $tmp_file_path = $archive_path.$temp_dir_short.'/'.$my_file_path; + $res = file_put_contents($tmp_file_path, $contents); + if ($res === false) { error_log('Could not write into file '.$tmp_file_path.' '.__FILE__.' '.__LINE__, 0); } + $files_cleanup[] = $tmp_file_path; + //error_log($tmp_path); die(); //$my_xml_file_path = api_htmlentities(api_utf8_encode($my_file_path), ENT_QUOTES, 'UTF-8'); $my_xml_file_path = $my_file_path; $my_sub_dir = dirname($my_file_path); @@ -8711,250 +8785,176 @@ class learnpath $my_resource->setAttribute('type', 'webcontent'); $my_resource->setAttribute('href', $my_xml_file_path); // adlcp:scormtype can be either 'sco' or 'asset'. - $my_resource->setAttribute('adlcp:scormtype', 'asset'); + $my_resource->setAttribute('adlcp:scormtype', 'sco'); // xml:base is the base directory to find the files declared in this resource. $my_resource->setAttribute('xml:base', ''); - // give a <file> child to the <resource> element. + // Give a <file> child to the <resource> element. $my_file = $xmldoc->createElement('file'); $my_file->setAttribute('href', $my_xml_file_path); $my_resource->appendChild($my_file); - $resources->appendChild($my_resource); - } - break; - case TOOL_QUIZ: - require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.class.php'; - $exe_id = $item->path; // Should be using ref when everything will be cleaned up in this regard. - $exe = new Exercise(); - $exe->read($exe_id); - $my_item = $xmldoc->createElement('item'); - $my_item->setAttribute('identifier', 'ITEM_'.$item->get_id()); - $my_item->setAttribute('identifierref', 'RESOURCE_'.$item->get_id()); - $my_item->setAttribute('isvisible', 'true'); - // Give a child element <title> to the <item> element. - $my_title = $xmldoc->createElement('title', htmlspecialchars(api_utf8_encode($item->get_title()), ENT_QUOTES, 'UTF-8')); - $my_item->appendChild($my_title); - $my_max_score = $xmldoc->createElement('max_score', $item->get_max()); - //$my_item->appendChild($my_max_score); - // Give a child element <adlcp:prerequisites> to the <item> element. - $my_prereqs = $xmldoc->createElement('adlcp:prerequisites', $item->get_prereq_string()); - $my_prereqs->setAttribute('type','aicc_script'); - $my_item->appendChild($my_prereqs); - // Give a child element <adlcp:masteryscore> to the <item> element. - $my_masteryscore = $xmldoc->createElement('adlcp:masteryscore', $item->get_mastery_score()); - $my_item->appendChild($my_masteryscore); - - // Attach this item to the organization element or hits parent if there is one. - if (!empty($item->parent) && $item->parent != 0) { - $children = $organization->childNodes; - for ($i = 0; $i < $children->length; $i++) { - $item_temp = $children->item($i); - if ($item_temp -> nodeName == 'item') { - if ($item_temp->getAttribute('identifier') == 'ITEM_'.$item->parent) { - $item_temp -> appendChild($my_item); - } - } - } - } else { - $organization->appendChild($my_item); - } - // Include export scripts. - require_once api_get_path(SYS_CODE_PATH).'exercice/export/scorm/scorm_export.php'; - - // Get the path of the file(s) from the course directory root - //$my_file_path = $item->get_file_path('scorm/'.$this->path.'/'); - $my_file_path = 'quiz_'.$item->get_id().'.html'; - // Write the contents of the exported exercise into a (big) html file - // to later pack it into the exported SCORM. The file will be removed afterwards. - $contents = export_exercise($exe_id, true); - $tmp_file_path = $archive_path.$temp_dir_short.'/'.$my_file_path; - $res = file_put_contents($tmp_file_path, $contents); - if ($res === false) { error_log('Could not write into file '.$tmp_file_path.' '.__FILE__.' '.__LINE__, 0); } - $files_cleanup[] = $tmp_file_path; - //error_log($tmp_path); die(); - //$my_xml_file_path = api_htmlentities(api_utf8_encode($my_file_path), ENT_QUOTES, 'UTF-8'); - $my_xml_file_path = $my_file_path; - $my_sub_dir = dirname($my_file_path); - $my_sub_dir = str_replace('\\', '/', $my_sub_dir); - //$my_xml_sub_dir = api_htmlentities(api_utf8_encode($my_sub_dir), ENT_QUOTES, 'UTF-8'); - $my_xml_sub_dir = $my_sub_dir; - // Give a <resource> child to the <resources> element. - $my_resource = $xmldoc->createElement('resource'); - $my_resource->setAttribute('identifier', 'RESOURCE_'.$item->get_id()); - $my_resource->setAttribute('type', 'webcontent'); - $my_resource->setAttribute('href', $my_xml_file_path); - // adlcp:scormtype can be either 'sco' or 'asset'. - $my_resource->setAttribute('adlcp:scormtype', 'sco'); - // xml:base is the base directory to find the files declared in this resource. - $my_resource->setAttribute('xml:base', ''); - // Give a <file> child to the <resource> element. - $my_file = $xmldoc->createElement('file'); - $my_file->setAttribute('href', $my_xml_file_path); - $my_resource->appendChild($my_file); - - // Get included docs. - $inc_docs = $item->get_resources_from_source(null,$tmp_file_path); - // Dependency to other files - not yet supported. - $i = 1; - foreach ($inc_docs as $doc_info) { - if (count($doc_info) < 1 || empty($doc_info[0])) { continue; } - $my_dep = $xmldoc->createElement('resource'); - $res_id = 'RESOURCE_'.$item->get_id().'_'.$i; - $my_dep->setAttribute('identifier', $res_id); - $my_dep->setAttribute('type', 'webcontent'); - $my_dep->setAttribute('adlcp:scormtype', 'asset'); - $my_dep_file = $xmldoc->createElement('file'); - // Check type of URL. - //error_log(__LINE__.'Now dealing with '.$doc_info[0].' of type '.$doc_info[1].'-'.$doc_info[2], 0); - if ($doc_info[1] == 'remote') { - // Remote file. Save url as is. - $my_dep_file->setAttribute('href', $doc_info[0]); - $my_dep->setAttribute('xml:base', ''); - } elseif ($doc_info[1] == 'local') { - switch ($doc_info[2]) { - case 'url': // Local URL - save path as url for now, don't zip file. - // Save file but as local file (retrieve from URL). - $abs_path = api_get_path(SYS_PATH).str_replace(api_get_path(WEB_PATH), '', $doc_info[0]); - $current_dir = dirname($abs_path); - $current_dir = str_replace('\\', '/', $current_dir); - $file_path = realpath($abs_path); - $file_path = str_replace('\\', '/', $file_path); - $my_dep_file->setAttribute('href', 'document/'.$file_path); - $my_dep->setAttribute('xml:base', ''); - if (strstr($file_path, $main_path) !== false) { - // The calculated real path is really inside the chamilo root path. - // Reduce file path to what's under the DocumentRoot. - $file_path = substr($file_path, strlen($root_path)); - //echo $file_path;echo '<br /><br />'; - //error_log('Reduced path: '.$file_path, 0); - $zip_files_abs[] = $file_path; - $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => 'document/'.$file_path); + // Get included docs. + $inc_docs = $item->get_resources_from_source(null,$tmp_file_path); + // Dependency to other files - not yet supported. + $i = 1; + foreach ($inc_docs as $doc_info) { + if (count($doc_info) < 1 || empty($doc_info[0])) { continue; } + $my_dep = $xmldoc->createElement('resource'); + $res_id = 'RESOURCE_'.$item->get_id().'_'.$i; + $my_dep->setAttribute('identifier', $res_id); + $my_dep->setAttribute('type', 'webcontent'); + $my_dep->setAttribute('adlcp:scormtype', 'asset'); + $my_dep_file = $xmldoc->createElement('file'); + // Check type of URL. + //error_log(__LINE__.'Now dealing with '.$doc_info[0].' of type '.$doc_info[1].'-'.$doc_info[2], 0); + if ($doc_info[1] == 'remote') { + // Remote file. Save url as is. + $my_dep_file->setAttribute('href', $doc_info[0]); + $my_dep->setAttribute('xml:base', ''); + } elseif ($doc_info[1] == 'local') { + switch ($doc_info[2]) { + case 'url': // Local URL - save path as url for now, don't zip file. + // Save file but as local file (retrieve from URL). + $abs_path = api_get_path(SYS_PATH).str_replace(api_get_path(WEB_PATH), '', $doc_info[0]); + $current_dir = dirname($abs_path); + $current_dir = str_replace('\\', '/', $current_dir); + $file_path = realpath($abs_path); + $file_path = str_replace('\\', '/', $file_path); $my_dep_file->setAttribute('href', 'document/'.$file_path); $my_dep->setAttribute('xml:base', ''); - } elseif (empty($file_path)) { - /*$document_root = substr(api_get_path(SYS_PATH), 0, strpos(api_get_path(SYS_PATH),api_get_path(REL_PATH))); - if (strpos($document_root,-1) == '/') { - $document_root = substr(0, -1, $document_root); - }*/ - $file_path = $_SERVER['DOCUMENT_ROOT'].$abs_path; - $file_path = str_replace('//', '/', $file_path); - if (file_exists($file_path)) { - $file_path = substr($file_path, strlen($current_dir)); // We get the relative path. - $zip_files[] = $my_sub_dir.'/'.$file_path; + if (strstr($file_path, $main_path) !== false) { + // The calculated real path is really inside the chamilo root path. + // Reduce file path to what's under the DocumentRoot. + $file_path = substr($file_path, strlen($root_path)); + //echo $file_path;echo '<br /><br />'; + //error_log('Reduced path: '.$file_path, 0); + $zip_files_abs[] = $file_path; $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => 'document/'.$file_path); $my_dep_file->setAttribute('href', 'document/'.$file_path); - $my_dep->setAttribute('xml:base', ''); + $my_dep->setAttribute('xml:base', ''); + } elseif (empty($file_path)) { + /*$document_root = substr(api_get_path(SYS_PATH), 0, strpos(api_get_path(SYS_PATH),api_get_path(REL_PATH))); + if (strpos($document_root,-1) == '/') { + $document_root = substr(0, -1, $document_root); + }*/ + $file_path = $_SERVER['DOCUMENT_ROOT'].$abs_path; + $file_path = str_replace('//', '/', $file_path); + if (file_exists($file_path)) { + $file_path = substr($file_path, strlen($current_dir)); // We get the relative path. + $zip_files[] = $my_sub_dir.'/'.$file_path; + $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => 'document/'.$file_path); + $my_dep_file->setAttribute('href', 'document/'.$file_path); + $my_dep->setAttribute('xml:base', ''); + } } - } - break; - case 'abs': // Absolute path from DocumentRoot. Save file and leave path as is in the zip. - $current_dir = dirname($current_course_path.'/'.$item->get_file_path()).'/'; - $current_dir = str_replace('\\', '/', $current_dir); - $file_path = realpath($doc_info[0]); - $file_path = str_replace('\\', '/', $file_path); - $my_dep_file->setAttribute('href', $file_path); - $my_dep->setAttribute('xml:base', ''); - - if (strstr($file_path,$main_path) !== false) { - // The calculated real path is really inside the chamilo root path. - // Reduce file path to what's under the DocumentRoot. - $file_path = substr($file_path, strlen($root_path)); - //echo $file_path;echo '<br /><br />'; - //error_log('Reduced path: '.$file_path, 0); - $zip_files_abs[] = $file_path; - $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $file_path); - $my_dep_file->setAttribute('href', 'document/'.$file_path); - $my_dep->setAttribute('xml:base', ''); - } elseif (empty($file_path)) { - /*$document_root = substr(api_get_path(SYS_PATH), 0, strpos(api_get_path(SYS_PATH), api_get_path(REL_PATH))); - if (strpos($document_root,-1) == '/') { - $document_root = substr(0, -1, $document_root); - }*/ - $file_path = $_SERVER['DOCUMENT_ROOT'].$doc_info[0]; - $file_path = str_replace('//', '/', $file_path); - if (file_exists($file_path)) { - $file_path = substr($file_path,strlen($current_dir)); // We get the relative path. - $zip_files[] = $my_sub_dir.'/'.$file_path; - $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $file_path); - $my_dep_file->setAttribute('href', 'document/'.$file_path); - $my_dep->setAttribute('xml:base', ''); - } - } - break; - case 'rel': // Path relative to the current document. Save xml:base as current document's directory and save file in zip as subdir.file_path - if (substr($doc_info[0], 0, 2) == '..') { - // Relative path going up. + break; + case 'abs': // Absolute path from DocumentRoot. Save file and leave path as is in the zip. $current_dir = dirname($current_course_path.'/'.$item->get_file_path()).'/'; $current_dir = str_replace('\\', '/', $current_dir); - $file_path = realpath($current_dir.$doc_info[0]); + $file_path = realpath($doc_info[0]); $file_path = str_replace('\\', '/', $file_path); - //error_log($file_path.' <-> '.$main_path, 0); - if (strstr($file_path, $main_path) !== false) { - // The calculated real path is really inside Chamilo's root path. - // Reduce file path to what's under the DocumentRoot. + $my_dep_file->setAttribute('href', $file_path); + $my_dep->setAttribute('xml:base', ''); + if (strstr($file_path,$main_path) !== false) { + // The calculated real path is really inside the chamilo root path. + // Reduce file path to what's under the DocumentRoot. $file_path = substr($file_path, strlen($root_path)); - $file_path_dest = $file_path; - - // File path is courses/CHAMILO/document/.... - $info_file_path = explode('/', $file_path); - if ($info_file_path[0] == 'courses') { // Add character "/" in file path. - $file_path_dest = 'document/'.$file_path; - } - + //echo $file_path;echo '<br /><br />'; //error_log('Reduced path: '.$file_path, 0); $zip_files_abs[] = $file_path; - - $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $file_path_dest); + $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $file_path); $my_dep_file->setAttribute('href', 'document/'.$file_path); - $my_dep->setAttribute('xml:base', ''); + $my_dep->setAttribute('xml:base', ''); + } elseif (empty($file_path)) { + /*$document_root = substr(api_get_path(SYS_PATH), 0, strpos(api_get_path(SYS_PATH), api_get_path(REL_PATH))); + if (strpos($document_root,-1) == '/') { + $document_root = substr(0, -1, $document_root); + }*/ + $file_path = $_SERVER['DOCUMENT_ROOT'].$doc_info[0]; + $file_path = str_replace('//', '/', $file_path); + if (file_exists($file_path)) { + $file_path = substr($file_path,strlen($current_dir)); // We get the relative path. + $zip_files[] = $my_sub_dir.'/'.$file_path; + $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $file_path); + $my_dep_file->setAttribute('href', 'document/'.$file_path); + $my_dep->setAttribute('xml:base', ''); + } } - } else { - $zip_files[] = $my_sub_dir.'/'.$doc_info[0]; - $my_dep_file->setAttribute('href', $doc_info[0]); - $my_dep->setAttribute('xml:base', $my_xml_sub_dir); - } - break; - default: - $my_dep_file->setAttribute('href', $doc_info[0]); // ../../courses/ - $my_dep->setAttribute('xml:base', ''); - break; + break; + case 'rel': // Path relative to the current document. Save xml:base as current document's directory and save file in zip as subdir.file_path + if (substr($doc_info[0], 0, 2) == '..') { + // Relative path going up. + $current_dir = dirname($current_course_path.'/'.$item->get_file_path()).'/'; + $current_dir = str_replace('\\', '/', $current_dir); + $file_path = realpath($current_dir.$doc_info[0]); + $file_path = str_replace('\\', '/', $file_path); + //error_log($file_path.' <-> '.$main_path, 0); + if (strstr($file_path, $main_path) !== false) { + // The calculated real path is really inside Chamilo's root path. + // Reduce file path to what's under the DocumentRoot. + + $file_path = substr($file_path, strlen($root_path)); + $file_path_dest = $file_path; + + // File path is courses/CHAMILO/document/.... + $info_file_path = explode('/', $file_path); + if ($info_file_path[0] == 'courses') { // Add character "/" in file path. + $file_path_dest = 'document/'.$file_path; + } + + //error_log('Reduced path: '.$file_path, 0); + $zip_files_abs[] = $file_path; + + $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $file_path_dest); + $my_dep_file->setAttribute('href', 'document/'.$file_path); + $my_dep->setAttribute('xml:base', ''); + } + } else { + $zip_files[] = $my_sub_dir.'/'.$doc_info[0]; + $my_dep_file->setAttribute('href', $doc_info[0]); + $my_dep->setAttribute('xml:base', $my_xml_sub_dir); + } + break; + default: + $my_dep_file->setAttribute('href', $doc_info[0]); // ../../courses/ + $my_dep->setAttribute('xml:base', ''); + break; + } } + $my_dep->appendChild($my_dep_file); + $resources->appendChild($my_dep); + $dependency = $xmldoc->createElement('dependency'); + $dependency->setAttribute('identifierref', $res_id); + $my_resource->appendChild($dependency); + $i++; } - $my_dep->appendChild($my_dep_file); - $resources->appendChild($my_dep); - $dependency = $xmldoc->createElement('dependency'); - $dependency->setAttribute('identifierref', $res_id); - $my_resource->appendChild($dependency); - $i++; - } - $resources->appendChild($my_resource); - $zip_files[] = $my_file_path; + $resources->appendChild($my_resource); + $zip_files[] = $my_file_path; break; default: - // Get the path of the file(s) from the course directory root - $my_file_path = 'non_exportable.html'; - //$my_xml_file_path = api_htmlentities(api_utf8_encode($my_file_path), ENT_COMPAT, 'UTF-8'); - $my_xml_file_path = $my_file_path; - $my_sub_dir = dirname($my_file_path); - $my_sub_dir = str_replace('\\', '/', $my_sub_dir); - //$my_xml_sub_dir = api_htmlentities(api_utf8_encode($my_sub_dir), ENT_COMPAT, 'UTF-8'); - $my_xml_sub_dir = $my_sub_dir; - // Give a <resource> child to the <resources> element. - $my_resource = $xmldoc->createElement('resource'); - $my_resource->setAttribute('identifier', 'RESOURCE_'.$item->get_id()); - $my_resource->setAttribute('type', 'webcontent'); - + // Get the path of the file(s) from the course directory root + $my_file_path = 'non_exportable.html'; + //$my_xml_file_path = api_htmlentities(api_utf8_encode($my_file_path), ENT_COMPAT, 'UTF-8'); + $my_xml_file_path = $my_file_path; + $my_sub_dir = dirname($my_file_path); + $my_sub_dir = str_replace('\\', '/', $my_sub_dir); + //$my_xml_sub_dir = api_htmlentities(api_utf8_encode($my_sub_dir), ENT_COMPAT, 'UTF-8'); + $my_xml_sub_dir = $my_sub_dir; + // Give a <resource> child to the <resources> element. + $my_resource = $xmldoc->createElement('resource'); + $my_resource->setAttribute('identifier', 'RESOURCE_'.$item->get_id()); + $my_resource->setAttribute('type', 'webcontent'); $my_resource->setAttribute('href', $folder_name.'/'.$my_xml_file_path); - // adlcp:scormtype can be either 'sco' or 'asset'. - $my_resource->setAttribute('adlcp:scormtype', 'asset'); - // xml:base is the base directory to find the files declared in this resource. - $my_resource->setAttribute('xml:base', ''); - // Give a <file> child to the <resource> element. - $my_file = $xmldoc->createElement('file'); - $my_file->setAttribute('href', 'document/'.$my_xml_file_path); - $my_resource->appendChild($my_file); - $resources->appendChild($my_resource); + // adlcp:scormtype can be either 'sco' or 'asset'. + $my_resource->setAttribute('adlcp:scormtype', 'asset'); + // xml:base is the base directory to find the files declared in this resource. + $my_resource->setAttribute('xml:base', ''); + // Give a <file> child to the <resource> element. + $my_file = $xmldoc->createElement('file'); + $my_file->setAttribute('href', 'document/'.$my_xml_file_path); + $my_resource->appendChild($my_file); + $resources->appendChild($my_resource); break; } } @@ -8969,21 +8969,19 @@ class learnpath // then add the file to the zip, then destroy the file (this is done automatically). // http://www.reload.ac.uk/scormplayer.html - once done, don't forget to close FS#138 - //error_log(print_r($zip_files,true), 0); foreach ($zip_files as $file_path) { - if (empty($file_path)) { continue; } - //error_log(__LINE__.'getting document from '.$sys_course_path.$_course['path'].'/'.$file_path.' removing '.$sys_course_path.$_course['path'].'/',0); + if (empty($file_path)) { + continue; + } + $dest_file = $archive_path.$temp_dir_short.'/'.$file_path; $this->create_path($dest_file); - //error_log('copy '.api_get_path(SYS_COURSE_PATH).$_course['path'].'/'.$file_path.' to '.api_get_path(SYS_ARCHIVE_PATH).$temp_dir_short.'/'.$file_path,0); - //echo $main_path.$file_path.'<br />'; @copy($sys_course_path.$_course['path'].'/'.$file_path, $dest_file); // Check if the file needs a link update. if (in_array($file_path, array_keys($link_updates))) { $string = file_get_contents($dest_file); unlink($dest_file); foreach ($link_updates[$file_path] as $old_new) { - //error_log('Replacing '.$old_new['orig'].' by '.$old_new['dest'].' in '.$file_path, 0); // This is an ugly hack that allows .flv files to be found by the flv player that // will be added in document/main/inc/lib/flv_player/flv_player.swf and that needs // to find the flv to play in document/main/, so we replace main/ in the flv path by @@ -8997,11 +8995,8 @@ class learnpath if (strpos("main/default_course_document", $old_new['dest'] === false)) { $new_dest = str_replace('document/', $mult.'document/', $old_new['dest']); } else { - //$new_dest = str_replace('main/default_course_document', $mult.'document/main/default_course_document', $old_new['dest']); $new_dest = $old_new['dest']; } - - //$string = str_replace($old_new['orig'], $old_new['dest'], $string); $string = str_replace($old_new['orig'], $new_dest, $string); //Add files inside the HTMLs @@ -9014,23 +9009,21 @@ class learnpath } } foreach ($zip_files_abs as $file_path) { - if (empty($file_path)) { continue; } - //error_log(__LINE__.'checking existence of '.$main_path.$file_path.'', 0); - if (!is_file($main_path.$file_path) || !is_readable($main_path.$file_path)) { continue; } - //error_log(__LINE__.'getting document from '.$main_path.$file_path.' removing '.api_get_path(SYS_COURSE_PATH).$_course['path'].'/', 0); + if (empty($file_path)) { + continue; + } + if (!is_file($main_path.$file_path) || !is_readable($main_path.$file_path)) { + continue; + } + $dest_file = $archive_path.$temp_dir_short.'/document/'.$file_path; $this->create_path($dest_file); - //error_log('Created path '.api_get_path(SYS_ARCHIVE_PATH).$temp_dir_short.'/document/'.$file_path, 0); - //error_log('copy '.api_get_path(SYS_COURSE_PATH).$_course['path'].'/'.$file_path.' to '.api_get_path(SYS_ARCHIVE_PATH).$temp_dir_short.'/'.$file_path, 0); - //echo $main_path.$file_path.' - '.$dest_file.'<br />'; - copy($main_path.$file_path, $dest_file); // Check if the file needs a link update. if (in_array($file_path, array_keys($link_updates))) { $string = file_get_contents($dest_file); unlink($dest_file); foreach ($link_updates[$file_path] as $old_new) { - //error_log('Replacing '.$old_new['orig'].' by '.$old_new['dest'].' in '.$file_path, 0); // This is an ugly hack that allows .flv files to be found by the flv player that // will be added in document/main/inc/lib/flv_player/flv_player.swf and that needs // to find the flv to play in document/main/, so we replace main/ in the flv path by @@ -9044,7 +9037,6 @@ class learnpath } } - if (is_array($links_to_create)) { foreach ($links_to_create as $file => $link) { $file_content = '<!DOCTYPE html><head> @@ -9124,15 +9116,18 @@ EOD; if ($res === false) { error_log('Could not delete temp file '.$file.' '.__FILE__.' '.__LINE__, 0); } } // Send file to client. - //$name = 'scorm_export_'.$this->lp_id.'.zip'; require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php'; $name = replace_dangerous_char($this->get_name()).'.zip'; - DocumentManager::file_send_for_download($temp_zip_file, true, $name); } - public function scorm_export_to_pdf($lp_id) { + /** + * @param int $lp_id + * @return bool + */ + public function scorm_export_to_pdf($lp_id) + { $lp_id = intval($lp_id); $files_to_export = array(); $course_data = api_get_course_info($this->cc); @@ -9175,11 +9170,13 @@ EOD; } /** - * Temp function to be moved in main_api or the best place around for this. Creates a file path - * if it doesn't exist + * Temp function to be moved in main_api or the best place around for this. + * Creates a file path if it doesn't exist + * @param string $path */ - public function create_path($path) { - $path_bits = split('/', dirname($path)); + public function create_path($path) + { + $path_bits = explode('/', dirname($path)); // IS_WINDOWS_OS has been defined in main_api.lib.php $path_built = IS_WINDOWS_OS ? '' : '/'; @@ -9201,7 +9198,8 @@ EOD; * Delete the image relative to this learning path. No parameter. Only works on instanciated object. * @return boolean The results of the unlink function, or false if there was no image to start with */ - public function delete_lp_image() { + public function delete_lp_image() + { $img = $this->get_preview_image(); if ($img != '') { $del_file = $this->get_preview_image_path(null, 'sys'); @@ -9222,7 +9220,8 @@ EOD; * @param array The image array, coming from the $_FILES superglobal * @return boolean True on success, false on error */ - public function upload_image($image_array) { + public function upload_image($image_array) + { $image_moved = false; if (!empty ($image_array['name'])) { $upload_ok = process_uploaded_file($image_array); @@ -9282,6 +9281,10 @@ EOD; return false; } + /** + * @param int $lp_id + * @param string $status + */ public function set_autolunch($lp_id, $status) { $course_id = api_get_course_int_id(); @@ -9328,6 +9331,9 @@ EOD; return $row_max->previous; } + /** + * Copies an LP + */ public function copy() { $main_path = api_get_path(SYS_CODE_PATH); @@ -9354,7 +9360,8 @@ EOD; $course_restorer->restore(api_get_course_id(), api_get_session_id(), false, false); } - function verify_document_size($s) { + function verify_document_size($s) + { $post_max = ini_get('post_max_size'); $upl_max = ini_get('upload_max_filesize'); $documents_total_space = DocumentManager::documents_total_space();