/** * Method to copy files and directories recursively * * @param $source * @param $dest * @param bool $override * @throws \Exception */ function copyr($source, $dest, $override = false) { $dir = opendir($source); if (!is_dir($dest)) { mkdir($dest); } else { chmod($dest, 0755); } if (is_resource($dir)) { while (false !== ($file = readdir($dir))) { if ($file != '.' && $file != '..') { if (is_dir($source . DIRECTORY_SEPARATOR . $file)) { copyr($source . DIRECTORY_SEPARATOR . $file, $dest . DIRECTORY_SEPARATOR . $file); } elseif (is_readable($dest . DIRECTORY_SEPARATOR . $file) && $override === true) { copy($source . DIRECTORY_SEPARATOR . $file, $dest . DIRECTORY_SEPARATOR . $file); } elseif (!is_readable($dest . DIRECTORY_SEPARATOR . $file)) { copy($source . DIRECTORY_SEPARATOR . $file, $dest . DIRECTORY_SEPARATOR . $file); } } } } else { throw new \Exception("readdir() expects parameter 1 to be resource", 10); } closedir($dir); }
function profile_2012100501($user) { global $CONFIG; $data_root = $CONFIG->dataroot; $join_date = $user->getTimeCreated(); date_default_timezone_set('UTC'); $user_path_utc = date('Y/m/d/', $join_date) . $user->guid; $user_path_utc = "{$data_root}{$user_path_utc}"; date_default_timezone_set('Europe/Berlin'); $user_path = date('Y/m/d/', $join_date) . $user->guid; $user_path = "{$data_root}{$user_path}"; $user_path2 = date('Y/m/d', $join_date); $user_path2 = "{$data_root}{$user_path2}"; if ($user_path == $user_path_utc) { return true; } // error_log("check $user_path_utc"); if (file_exists($user_path_utc)) { if (!file_exists($user_path)) { mkdir($user_path, 0700, true); } error_log("merge files: {$user_path_utc}, {$user_path}"); copyr($user_path_utc, $user_path2); } return true; }
/** * Copy a file, or recursively copy a folder and its contents * * @author Aidan Lister <*****@*****.**> * @version 1.0.1 * @link http://aidanlister.com/2004/04/recursively-copying-directories-in-php/ * @param string $source Source path * @param string $dest Destination path * @return bool Returns TRUE on success, FALSE on failure */ function copyr($source, $dest) { // Check for symlinks if (is_link($source)) { return symlink(readlink($source), $dest); } // Simple copy for a file if (is_file($source)) { return copy($source, $dest); } // Make destination directory if (!is_dir($dest)) { mkdir($dest); } // Loop through the folder $dir = dir($source); while (false !== ($entry = $dir->read())) { // Skip pointers if ($entry == '.' || $entry == '..') { continue; } // Deep copy directories copyr("{$source}/{$entry}", "{$dest}/{$entry}"); } // Clean up $dir->close(); return true; }
public function install($filename) { $src = ROOT . '/sys/tmp/' . $filename; $dest = ROOT . '/sys/tmp/install_plugin/'; Zip::extractZip($src, $dest); if (!file_exists($dest)) { $this->errors = __('Some error occurred'); return false; } $tmp_plugin_path = glob($dest . '*', GLOB_ONLYDIR); $tmp_plugin_path = $tmp_plugin_path[0]; $plugin_basename = substr(strrchr($tmp_plugin_path, '/'), 1); $plugin_path = ROOT . '/sys/plugins/' . $plugin_basename; copyr($dest, ROOT . '/sys/plugins/', 0755); $this->files = getDirFiles($plugin_path); if (file_exists($plugin_path . '/config.dat')) { $config = json_decode(file_get_contents($plugin_path . '/config.dat'), true); include_once $plugin_path . '/index.php'; $className = $config['className']; $obj = new $className(null); if (method_exists($obj, 'install')) { $obj->install(); } } _unlink($src); _unlink($dest); return true; }
function move_upload_directories() { global $sl_upload_path, $sl_path; if (!is_dir(ABSPATH . "wp-content/uploads")) { mkdir(ABSPATH . "wp-content/uploads", 0755); } if (!is_dir($sl_upload_path)) { mkdir($sl_upload_path, 0755); } if (is_dir($sl_path . "/addons") && !is_dir($sl_upload_path . "/addons")) { copyr($sl_path . "/addons", $sl_upload_path . "/addons"); } if (is_dir($sl_path . "/themes") && !is_dir($sl_upload_path . "/themes")) { copyr($sl_path . "/themes", $sl_upload_path . "/themes"); } if (is_dir($sl_path . "/languages") && !is_dir($sl_upload_path . "/languages")) { copyr($sl_path . "/languages", $sl_upload_path . "/languages"); } if (is_dir($sl_path . "/images") && !is_dir($sl_upload_path . "/images")) { copyr($sl_path . "/images", $sl_upload_path . "/images"); } //mkdir($sl_upload_path . "/addons", 0755); //mkdir($sl_upload_path . "/themes", 0755); //mkdir($sl_upload_path . "/languages", 0755); if (!is_dir($sl_upload_path . "/custom-icons")) { mkdir($sl_upload_path . "/custom-icons", 0755); } //mkdir($sl_upload_path . "/images", 0755); if (!is_dir($sl_upload_path . "/custom-css")) { mkdir($sl_upload_path . "/custom-css", 0755); } //copyr($sl_path . "/store-locator.css", $sl_upload_path . "/custom-css/store-locator.css"); }
/** * Recursively copies from one directory to another * * @access public * @param string * @param string * @return array */ function copyr($source, $dest) { // Simple copy for a file if (is_file($source)) { return copy($source, $dest); } // Make destination directory if (!is_dir($dest)) { mkdir($dest); } // If the source is a symlink if (is_link($source)) { $link_dest = readlink($source); return symlink($link_dest, $dest); } // Loop through the folder $dir = dir($source); if (!is_object($dir)) { return FALSE; } while (false !== ($entry = $dir->read())) { // Skip pointers if ($entry == '.' or $entry == '..') { continue; } // Deep copy directories if ($dest !== "{$source}/{$entry}") { copyr("{$source}/{$entry}", "{$dest}/{$entry}"); } } // Clean up $dir->close(); return true; }
function copyr($source, $dest) { if (is_link($source)) { return symlink(readlink($source), $dest); } if (is_file($source)) { $copied = copy($source, $dest); $content = file_get_contents($dest); $content = str_replace("Forone\\Admin\\Controllers", "App\\Http\\Controllers\\Forone\\Admin\\Controllers", $content); file_put_contents($dest, $content); return $copied; } if (!is_dir($dest)) { mkdir($dest, 0777, true); } $dir = dir($source); while (false !== ($entry = $dir->read())) { if ($entry == '.' || $entry == '..') { continue; } copyr("{$source}/{$entry}", "{$dest}/{$entry}"); } $dir->close(); return true; }
function copyr($source, $dest) { if (is_file($source)) { return copy($source, $dest); } if (!is_dir($dest)) { mkdir($dest); } $dir = dir($source); while (false !== ($entry = $dir->read())) { if ($entry == '.' || $entry == '..') { continue; } if ($dest !== "{$source}/{$entry}") { copyr("{$source}/{$entry}", "{$dest}/{$entry}"); } } $dir->close(); return true; }
/** * Copy a file, or recursively copy a folder and its contents * * @author Aidan Lister <*****@*****.**> * @version 1.0.1 * @link http://aidanlister.com/repos/v/function.copyr.php * @param string $source Source path * @param string $dest Destination path * @return bool Returns TRUE on success, FALSE on failure */ function copyr($source, $dest) { global $CFG; // Simple copy for a file if (is_file($source)) { return copy($source, $dest); } // Make destination directory if (!is_dir($dest)) { mkdir($dest, $CFG->directorypermissions, true); } // Loop through the folder $dir = dir($source); while (false !== ($entry = $dir->read())) { // Skip pointers if ($entry == '.' || $entry == '..') { continue; } // Deep copy directories if ($dest !== "{$source}/{$entry}") { copyr("{$source}/{$entry}", "{$dest}/{$entry}"); } } // Clean up $dir->close(); return true; }
if ($imgid > 10000) { error('admin.php?action=designs&job=design_import', 'Execution stopped: Buffer overflow (Images)'); } } $imgdir = 'images/' . $imgid; } else { $tplid = $row['images']; } if (!empty($ini['template'])) { copyr($tempdir . 'templates', $tpldir); } if (!empty($ini['stylesheet'])) { copyr($tempdir . 'designs', $cssdir); } if (!empty($ini['images'])) { copyr($tempdir . 'images', $imgdir); } $db->query("INSERT INTO `{$db->pre}designs` (`template` , `stylesheet` , `images` , `name`) VALUES ('{$tplid}', '{$cssid}', '{$imgid}', '{$ini['name']}')"); unset($archive); if ($del > 0) { $filesystem->unlink($file); } rmdirr($tempdir); } $delobj = $scache->load('loaddesign'); $delobj->delete(); ok('admin.php?action=designs&job=design', 'Design "' . $ini['name'] . '" successfully imported!'); } elseif ($job == 'design_export') { $id = $gpc->get('id', int); echo head(); ?>
} else { $sitep = $_POST["site"]; } //get site $site = $blSite->getSiteByName($sitep); //css folder $csssourcefolder = getcwd() . '/sites/' . $site->getOriginalName() . '/css'; $cssdestinationfolder = getcwd() . '/html/' . $site->getName() . '/css'; if (is_dir($csssourcefolder)) { copyr($csssourcefolder, $cssdestinationfolder); } //scripts folder $scriptssourcefolder = getcwd() . '/sites/' . $site->getOriginalName() . '/scripts'; $scriptsdestinationfolder = getcwd() . '/html/' . $site->getName() . '/scripts'; if (is_dir($scriptssourcefolder)) { copyr($scriptssourcefolder, $scriptsdestinationfolder); //update facebox.js file $filename = $scriptsdestinationfolder . "/facebox/facebox.js"; // open file $data = file_get_contents($filename); // replace string $data = str_replace("/media_sites/sites/" . $site->getName() . "/", "", $data); // write file file_put_contents($filename, $data); } //images folder $imagessourcefolder = getcwd() . '/sites/' . $site->getOriginalName() . '/images'; $imagesdestinationfolder = getcwd() . '/html/' . $site->getName() . '/images'; if (is_dir($imagessourcefolder)) { copyr($imagessourcefolder, $imagesdestinationfolder); }
/** * Method create directory with domain specific config * Function create the directory by copy the html/domains/_default * * @param string $domainname name of directory with domain config files * @param array $errors array with error messages * @return bool return TRUE on success, FALSE on failure */ function create_domain_config_dir($domainname, &$errors) { $serweb_root = dirname(dirname(dirname(__FILE__))) . "/"; $target = $serweb_root . "html/domains/" . $domainname; if (file_exists($target)) { return true; } FileJournal::add_created_file($target); if (false === copyr($serweb_root . "html/domains/_default", $target)) { log_errors(PEAR::raiseError("Can't create domain specific config", NULL, NULL, NULL, "Can't create dicetory with domain config. Directory:" . $target), $errors); return false; } return true; }
public function copyResourcesFolder($type = 'site', $overWrite = true) { // Get theme path $path = Yii::getPathOfAlias('themes.' . $type) . '/www'; $dest = Yii::getPathOfAlias('themes.' . $this->dirname . '/www'); $files = $this->getResourcesFiles($type); foreach ($files as $key => $file) { $source = $file; $file = str_replace($this->getSourceWwwDir($type), '', $file); $inserts[] = array('file_name' => end(explode('/', $file)), 'file_location' => '/www' . $file, 'file_directory' => 'www/' . trim(str_replace(array('/www', end(explode('/', $file))), '', $file), '/'), 'file_ext' => end(explode('.', $file)), 'content' => file_get_contents($source)); } foreach ($inserts as $insert) { // Check if the file location exists $exists = ThemeFile::model()->exists('theme_id=:id AND file_location=:location', array(':id' => $this->id, ':location' => $insert['file_location'])); if (!$exists) { // Add to the db $themeFile = new ThemeFile(); $themeFile->theme_id = $this->id; $themeFile->file_name = $insert['file_name']; $themeFile->file_location = $insert['file_location']; $themeFile->file_directory = $insert['file_directory']; $themeFile->file_ext = $insert['file_ext']; $themeFile->content = $insert['content']; $themeFile->save(false); } } if ($path) { // We copy themes/$type/www to the new theme location return copyr($path, $dest, $overWrite); } return false; }
} } $filesystem->mkdir("templates/{$template}/", 0777); } if ($stylesheet == 0) { $stylesheet = 1; while (is_dir('designs/' . $stylesheet)) { $stylesheet++; if ($stylesheet > 10000) { error('admin.php?action=designs&job=design_add', $lang->phrase('admin_design_buffer_overflow_css')); } } $result = $db->query("SELECT stylesheet FROM {$db->pre}designs WHERE id = '{$config['templatedir']}' LIMIT 1"); $info = $db->fetch_assoc($result); $filesystem->mkdir("designs/{$stylesheet}/", 0777); copyr("designs/{$info['stylesheet']}/", "designs/{$stylesheet}/"); } if ($images == 0) { $images = 1; while (is_dir('images/' . $images)) { $images++; if ($images > 10000) { error('admin.php?action=designs&job=design_add', $lang->phrase('admin_design_buffer_overflow_images')); } } $filesystem->mkdir("images/{$images}/", 0777); } $delobj = $scache->load('loaddesign'); $delobj->delete(); $db->query("INSERT INTO {$db->pre}designs SET template = '{$template}', stylesheet = '{$stylesheet}', images = '{$images}', publicuse = '{$use}', name = '{$name}'", __LINE__, __FILE__); ok('admin.php?action=designs&job=design', $lang->phrase('admin_design_design_successfully_added'));
function mover($source, $dest) { global $filesystem; if (!is_dir($dest)) { $filesystem->mkdir($dest, 0777); } if ($filesystem->rename($source, $dest)) { return true; } else { if (copyr($source, $dest)) { rmdirr($source); return true; } return false; } }
/** * function adapted from a php.net comment * copy recursively a folder * @param the source folder * @param the dest folder * @param an array of excluded file_name (without extension) * @param copied_files the returned array of copied files */ function copyr($source, $dest, $exclude = array(), $copied_files = array()) { if (empty($dest)) { return false; } // Simple copy for a file if (is_file($source)) { $path_info = pathinfo($source); if (!in_array($path_info['filename'], $exclude)) { copy($source, $dest); } return true; } elseif (!is_dir($source)) { //then source is not a dir nor a file, return return false; } // Make destination directory. if (!is_dir($dest)) { mkdir($dest, api_get_permissions_for_new_directories()); } // Loop through the folder. $dir = dir($source); while (false !== ($entry = $dir->read())) { // Skip pointers if ($entry == '.' || $entry == '..') { continue; } // Deep copy directories. if ($dest !== "{$source}/{$entry}") { $files = copyr("{$source}/{$entry}", "{$dest}/{$entry}", $exclude, $copied_files); } } // Clean up. $dir->close(); return true; }
/** * Copies the static files (stylesheets etc.) into the export */ private function copy_static_files() { global $THEME, $SESSION; require_once 'file.php'; $staticdir = $this->get('exportdir') . '/' . $this->get('rootdir') . '/static/'; $directoriestocopy = array(); // Get static directories from each theme for HTML export $themestaticdirs = $THEME->get_path('', true, 'export/html'); foreach ($themestaticdirs as $theme => $dir) { $themedir = $staticdir . 'theme/' . $theme . '/static/'; $directoriestocopy[$dir] = $themedir; if (!check_dir_exists($themedir)) { throw new SystemException("Could not create theme directory for theme {$theme}"); } } // Smilies $directoriestocopy[get_config('docroot') . 'js/tinymce/plugins/emoticons/img'] = $staticdir . 'smilies/'; $filestocopy = array(get_config('docroot') . 'theme/views.css' => $staticdir . 'views.css'); foreach ($this->pluginstaticdirs as $dir) { $destinationdir = str_replace('export/html/', '', $dir); if (!check_dir_exists($staticdir . $destinationdir)) { $SESSION->add_error_msg(get_string('couldnotcreatestaticdirectory', 'export', $destinationdir)); } foreach ($themestaticdirs as $theme => $themedir) { if (file_exists(get_config('docroot') . 'theme/' . $theme . '/' . $dir)) { $directoriestocopy[get_config('docroot') . 'theme/' . $theme . '/' . $dir] = $staticdir . $destinationdir; } } } foreach ($directoriestocopy as $from => $to) { if (!copyr($from, $to)) { $SESSION->add_error_msg(get_string('couldnotcopyfilesfromto', 'export', $from, $to)); } } foreach ($filestocopy as $from => $to) { if (!is_file($from) || !copy($from, $to)) { $SESSION->add_error_msg(get_string('couldnotcopystaticfile', 'export', $from)); } } }
/** * // TODO: The output encoding should be equal to the system encoding. * * Exports the learning path as a SCORM package. This is the main function that * gathers the content, transforms it, writes the imsmanifest.xml file, zips the * whole thing and returns the zip. * * This method needs to be called in PHP5, as it will fail with non-adequate * XML package (like the ones for PHP4), and it is *not* a static method, so * you need to call it on a learnpath object. * @TODO The method might be redefined later on in the scorm class itself to avoid * creating a SCORM structure if there is one already. However, if the initial SCORM * path has been modified, it should use the generic method here below. * @TODO link this function with the export_lp() function in the same class * @param string Optional name of zip file. If none, title of learnpath is * domesticated and trailed with ".zip" * @return string Returns the zip package string, or null if error */ public function scorm_export() { $_course = api_get_course_info(); $course_id = $_course['real_id']; // Remove memory and time limits as much as possible as this might be a long process... if (function_exists('ini_set')) { api_set_memory_limit('128M'); ini_set('max_execution_time', 600); } // Create the zip handler (this will remain available throughout the method). $archive_path = api_get_path(SYS_ARCHIVE_PATH); $sys_course_path = api_get_path(SYS_COURSE_PATH); $temp_dir_short = uniqid(); $temp_zip_dir = $archive_path . '/' . $temp_dir_short; $temp_zip_file = $temp_zip_dir . '/' . md5(time()) . '.zip'; $zip_folder = new PclZip($temp_zip_file); $current_course_path = api_get_path(SYS_COURSE_PATH) . api_get_course_path(); $root_path = $main_path = api_get_path(SYS_PATH); $files_cleanup = array(); // Place to temporarily stash the zip file. // create the temp dir if it doesn't exist // 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 { // Cleanup: Check the temp dir for old files and delete them. $handle = opendir($temp_zip_dir); while (false !== ($file = readdir($handle))) { if ($file != '.' && $file != '..') { unlink("{$temp_zip_dir}/{$file}"); } } closedir($handle); } $zip_files = $zip_files_abs = $zip_files_dist = array(); if (is_dir($current_course_path . '/scorm/' . $this->path) && is_file($current_course_path . '/scorm/' . $this->path . '/imsmanifest.xml')) { // Remove the possible . at the end of the path. $dest_path_to_lp = substr($this->path, -1) == '.' ? substr($this->path, 0, -1) : $this->path; $dest_path_to_scorm_folder = str_replace('//', '/', $temp_zip_dir . '/scorm/' . $dest_path_to_lp); 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). // This structure is developed following regulations for SCORM 1.2 packaging in the SCORM 1.2 Content // 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'); $root->setAttribute('xmlns', 'http://www.imsproject.org/xsd/imscp_rootv1p1p2'); $root->setAttribute('xmlns:adlcp', 'http://www.adlnet.org/xsd/adlcp_rootv1p2'); $root->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $root->setAttribute('xsi:schemaLocation', 'http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd'); // Build mandatory sub-root container elements. $metadata = $xmldoc->createElement('metadata'); $md_schema = $xmldoc->createElement('schema', 'ADL SCORM'); $metadata->appendChild($md_schema); $md_schemaversion = $xmldoc->createElement('schemaversion', '1.2'); $metadata->appendChild($md_schemaversion); $root->appendChild($metadata); $organizations = $xmldoc->createElement('organizations'); $resources = $xmldoc->createElement('resources'); // Build the only organization we will use in building our learnpaths. $organizations->setAttribute('default', 'chamilo_scorm_export'); $organization = $xmldoc->createElement('organization'); $organization->setAttribute('identifier', 'chamilo_scorm_export'); // To set the title of the SCORM entity (=organization), we take the name given // in Chamilo and convert it to HTML entities using the Chamilo charset (not the // learning path charset) as it is the encoding that defines how it is stored // in the database. Then we convert it to HTML entities again as the "&" character // alone is not authorized in XML (must be &). // The title is then decoded twice when extracting (see scorm::parse_manifest). $org_title = $xmldoc->createElement('title', api_utf8_encode($this->get_name())); $organization->appendChild($org_title); $folder_name = 'document'; // Removes the learning_path/scorm_folder path when exporting see #4841 $path_to_remove = null; $result = $this->generate_lp_folder($_course); if (isset($result['dir']) && strpos($result['dir'], 'learning_path')) { $path_to_remove = 'document' . $result['dir']; $path_to_replace = $folder_name . '/'; } //Fixes chamilo scorm exports if ($this->ref == 'chamilo_scorm_export') { $path_to_remove = 'scorm/' . $this->path . '/document/'; } // 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 { $inc_docs = $item->get_resources_from_source(); } // Give a child element <item> to the <organization> element. $my_item_id = $item->get_id(); $my_item = $xmldoc->createElement('item'); $my_item->setAttribute('identifier', 'ITEM_' . $my_item_id); $my_item->setAttribute('identifierref', 'RESOURCE_' . $my_item_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', $this->get_scorm_prereq_string($my_item_id)); $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 hits parent if there is one. if (!empty($item->parent) && $item->parent != 0) { $children = $organization->childNodes; $possible_parent =& $this->get_scorm_xml_node($children, 'ITEM_' . $item->parent); if (is_object($possible_parent)) { $possible_parent->appendChild($my_item); } else { if ($this->debug > 0) { error_log('Parent ITEM_' . $item->parent . ' of item ITEM_' . $my_item_id . ' not found'); } } } else { if ($this->debug > 0) { error_log('No parent'); } $organization->appendChild($my_item); } // Get the path of the file(s) from the course directory root. $my_file_path = $item->get_file_path('scorm/' . $this->path . '/'); if (!empty($path_to_remove)) { //From docs $my_xml_file_path = str_replace($path_to_remove, $path_to_replace, $my_file_path); //From quiz if ($this->ref == 'chamilo_scorm_export') { $path_to_remove = 'scorm/' . $this->path . '/'; $my_xml_file_path = str_replace($path_to_remove, '', $my_file_path); } } else { $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 = $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'. if ($item->type == 'sco') { $my_resource->setAttribute('adlcp:scormtype', 'sco'); } else { $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); // 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. $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', $file_path); $my_dep->setAttribute('xml:base', ''); 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) - 1); //echo $file_path;echo '<br /><br />'; //error_log(__LINE__.'Reduced url 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', $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; $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $file_path); $my_dep_file->setAttribute('href', $file_path); $my_dep->setAttribute('xml:base', ''); } } break; case 'abs': // Absolute path from DocumentRoot. Save file and leave path as is in the zip. $my_dep_file->setAttribute('href', $doc_info[0]); $my_dep->setAttribute('xml:base', ''); // The next lines fix a bug when using the "subdir" mode of Chamilo, whereas // an image path would be constructed as /var/www/subdir/subdir/img/foo.bar $abs_img_path_without_subdir = $doc_info[0]; $relp = api_get_path(REL_PATH); // The url-append config param. $pos = strpos($abs_img_path_without_subdir, $relp); if ($pos === 0) { $abs_img_path_without_subdir = '/' . substr($abs_img_path_without_subdir, strlen($relp)); } $file_path = realpath(api_get_path(SYS_PATH) . $abs_img_path_without_subdir); $file_path = str_replace('\\', '/', $file_path); $file_path = str_replace('//', '/', $file_path); // Prepare the current directory path (until just under 'document') with a trailing slash. $cur_path = substr($current_course_path, -1) == '/' ? $current_course_path : $current_course_path . '/'; // Check if the current document is in that path. if (strstr($file_path, $cur_path) !== false) { // The document is in that path, now get the relative path // to the containing document. $orig_file_path = dirname($cur_path . $my_file_path) . '/'; $orig_file_path = str_replace('\\', '/', $orig_file_path); $relative_path = ''; if (strstr($file_path, $cur_path) !== false) { //$relative_path = substr($file_path, strlen($orig_file_path)); $relative_path = str_replace($cur_path, '', $file_path); $file_path = substr($file_path, strlen($cur_path)); } else { // This case is still a problem as it's difficult to calculate a relative path easily // might still generate wrong links. //$file_path = substr($file_path,strlen($cur_path)); // Calculate the directory path to the current file (without trailing slash). $my_relative_path = dirname($file_path); $my_relative_path = str_replace('\\', '/', $my_relative_path); $my_relative_file = basename($file_path); // Calculate the directory path to the containing file (without trailing slash). $my_orig_file_path = substr($orig_file_path, 0, -1); $dotdot = ''; $subdir = ''; while (strstr($my_relative_path, $my_orig_file_path) === false && strlen($my_orig_file_path) > 1 && strlen($my_relative_path) > 1) { $my_relative_path2 = dirname($my_relative_path); $my_relative_path2 = str_replace('\\', '/', $my_relative_path2); $my_orig_file_path = dirname($my_orig_file_path); $my_orig_file_path = str_replace('\\', '/', $my_orig_file_path); $subdir = substr($my_relative_path, strlen($my_relative_path2) + 1) . '/' . $subdir; $dotdot += '../'; $my_relative_path = $my_relative_path2; } $relative_path = $dotdot . $subdir . $my_relative_file; } // Put the current document in the zip (this array is the array // that will manage documents already in the course folder - relative). $zip_files[] = $file_path; // Update the links to the current document in the containing document (make them relative). $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $relative_path); $my_dep_file->setAttribute('href', $file_path); $my_dep->setAttribute('xml:base', ''); } elseif (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)); //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); $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); 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. $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)); //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', ''); } } 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; } } $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; } 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 <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 = $my_file_path; $my_sub_dir = dirname($my_file_path); $my_sub_dir = str_replace('\\', '/', $my_sub_dir); $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: $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); } // 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 = ScormSection::export_exercise_to_scorm($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. 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); $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; $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. $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++; } $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'); $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); break; } } } $organizations->appendChild($organization); $root->appendChild($organizations); $root->appendChild($resources); $xmldoc->appendChild($root); // TODO: Add a readme file here, with a short description and a link to the Reload player // 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 foreach ($zip_files as $file_path) { if (empty($file_path)) { continue; } $dest_file = $archive_path . $temp_dir_short . '/' . $file_path; if (!empty($path_to_remove) && !empty($path_to_replace)) { $dest_file = str_replace($path_to_remove, $path_to_replace, $dest_file); } $this->create_path($dest_file); @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) { // 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 // ../../.. to return from inc/lib/flv_player to the document/main path. if (substr($old_new['dest'], -3) == 'flv' && substr($old_new['dest'], 0, 5) == 'main/') { $old_new['dest'] = str_replace('main/', '../../../', $old_new['dest']); } elseif (substr($old_new['dest'], -3) == 'flv' && substr($old_new['dest'], 0, 6) == 'video/') { $old_new['dest'] = str_replace('video/', '../../../../video/', $old_new['dest']); } //Fix to avoid problems with default_course_document if (strpos("main/default_course_document", $old_new['dest'] === false)) { //$newDestination = str_replace('document/', $mult.'document/', $old_new['dest']); $newDestination = $old_new['dest']; } else { $newDestination = str_replace('document/', '', $old_new['dest']); } $string = str_replace($old_new['orig'], $newDestination, $string); //Add files inside the HTMLs $new_path = str_replace('/courses/', '', $old_new['orig']); $destinationFile = $archive_path . $temp_dir_short . '/' . $old_new['dest']; if (file_exists($sys_course_path . $new_path)) { copy($sys_course_path . $new_path, $destinationFile); } } file_put_contents($dest_file, $string); } } foreach ($zip_files_abs as $file_path) { 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); 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) { // 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 // ../../.. to return from inc/lib/flv_player to the document/main path. if (substr($old_new['dest'], -3) == 'flv' && substr($old_new['dest'], 0, 5) == 'main/') { $old_new['dest'] = str_replace('main/', '../../../', $old_new['dest']); } $string = str_replace($old_new['orig'], $old_new['dest'], $string); } file_put_contents($dest_file, $string); } } if (is_array($links_to_create)) { foreach ($links_to_create as $file => $link) { $file_content = '<!DOCTYPE html><head> <meta charset="' . api_get_language_isocode() . '" /> <title>' . $link['title'] . '</title> </head> <body dir="' . api_get_text_direction() . '"> <div style="text-align:center"> <a href="' . $link['url'] . '">' . $link['title'] . '</a></div> </body> </html>'; file_put_contents($archive_path . $temp_dir_short . '/' . $file, $file_content); } } // Add non exportable message explanation. $lang_not_exportable = get_lang('ThisItemIsNotExportable'); $file_content = '<!DOCTYPE html><head> <meta charset="' . api_get_language_isocode() . '" /> <title>' . $lang_not_exportable . '</title> <meta http-equiv="Content-Type" content="text/html; charset=' . api_get_system_encoding() . '" /> </head> <body dir="' . api_get_text_direction() . '">'; $file_content .= <<<EOD <style> .error-message { font-family: arial, verdana, helvetica, sans-serif; border-width: 1px; border-style: solid; left: 50%; margin: 10px auto; min-height: 30px; padding: 5px; right: 50%; width: 500px; background-color: #FFD1D1; border-color: #FF0000; color: #000; } </style> <body> <div class="error-message"> {$lang_not_exportable} </div> </body> </html> EOD; if (!is_dir($archive_path . $temp_dir_short . '/document')) { @mkdir($archive_path . $temp_dir_short . '/document', api_get_permissions_for_new_directories()); } file_put_contents($archive_path . $temp_dir_short . '/document/non_exportable.html', $file_content); // Add the extra files that go along with a SCORM package. $main_code_path = api_get_path(SYS_CODE_PATH) . 'newscorm/packaging/'; $extra_files = scandir($main_code_path); foreach ($extra_files as $extra_file) { if (strpos($extra_file, '.') === 0) { continue; } else { $dest_file = $archive_path . $temp_dir_short . '/' . $extra_file; $this->create_path($dest_file); copy($main_code_path . $extra_file, $dest_file); } } // Finalize the imsmanifest structure, add to the zip, then return the zip. $manifest = @$xmldoc->saveXML(); $manifest = api_utf8_decode_xml($manifest); // The manifest gets the system encoding now. file_put_contents($archive_path . '/' . $temp_dir_short . '/imsmanifest.xml', $manifest); $zip_folder->add($archive_path . '/' . $temp_dir_short, PCLZIP_OPT_REMOVE_PATH, $archive_path . '/' . $temp_dir_short . '/'); // Clean possible temporary files. foreach ($files_cleanup as $file) { $res = unlink($file); if ($res === false) { error_log('Could not delete temp file ' . $file . ' ' . __FILE__ . ' ' . __LINE__, 0); } } $name = api_replace_dangerous_char($this->get_name()) . '.zip'; DocumentManager::file_send_for_download($temp_zip_file, true, $name); }
/** * Copies file(s) to given destination * * @param $path * @param $destination * @param bool $recursive * @return mixed * @throws \Exception */ public function copy($path, $destination, $recursive = false) { if ($recursive) { try { copyr($path, $destination); return true; } catch (\Exception $e) { return false; } } return copy($path, $destination); }
/** * Copies the static files (stylesheets etc.) into the export */ private function copy_static_files() { require_once 'file.php'; $staticdir = $this->get('exportdir') . '/' . $this->get('rootdir') . '/static/'; $directoriestocopy = array(); // Get static directories from each theme for HTML export $themestaticdirs = theme_get_path('', 'export/html/', true); foreach ($themestaticdirs as $theme => $dir) { $themedir = $staticdir . 'theme/' . $theme . '/static/'; $directoriestocopy[$dir] = $themedir; if (!check_dir_exists($themedir)) { throw new SystemException("Could not create theme directory for theme {$theme}"); } } // Smilies $directoriestocopy[get_config('docroot') . 'js/tinymce/plugins/emotions/images'] = $staticdir . 'smilies/'; $filestocopy = array(get_config('docroot') . 'theme/views.css' => $staticdir . 'views.css'); foreach ($this->pluginstaticdirs as $dir) { $destinationdir = str_replace('export/html/', '', $dir); if (!check_dir_exists($staticdir . $destinationdir)) { throw new SystemException("Could not create static directory {$destinationdir}"); } $directoriestocopy[get_config('docroot') . 'artefact/' . $dir] = $staticdir . $destinationdir; } foreach ($directoriestocopy as $from => $to) { if (!copyr($from, $to)) { throw new SystemException("Could not copy {$from} to {$to}"); } } foreach ($filestocopy as $from => $to) { if (!copy($from, $to)) { throw new SystemException("Could not copy static file {$from}"); } } }
function recursiveMoveDirectory($src, $dest) { if (copyr($src, $dest)) { recursiveRemoveDirectory($src); return TRUE; } return FALSE; }
function installation() { $source = "update/Hargassner-master"; $dest = "."; if (copyr($source, $dest)) { echo "Installation OK<br>"; } else { echo "Erreur d'installation : annulation de l'installation"; } }
$db->query("\n\t\t\t\t\tINSERT INTO {$db->pre}plugins\n\t\t\t\t\t(`name`,`module`,`ordering`,`required`,`position`)\n\t\t\t\t\tVALUES\n\t\t\t\t\t('{$plug['names'][$hook]}','{$packageid}','{$priority}','{$plug['required'][$hook]}','{$hook}')\n\t\t\t\t\t", __LINE__, __FILE__); $filesystem->unlink('cache/modules/' . $plugins->_group($hook) . '.php'); } } } // Templates $templates = array_merge(isset($plug['template']) ? $plug['template'] : array(), isset($com['template']) ? $com['template'] : array()); if (count($templates) > 0) { $tpldir = "templates/{$design['template']}/modules/{$packageid}/"; if (file_exists($tpldir)) { $filesystem->chmod($tpldir, 0777); } else { $filesystem->mkdir($tpldir, 0777); } $temptpldir = "{$tdir}templates/"; copyr($temptpldir, $tpldir); } // Custom Installer $confirm = true; ($code = $plugins->install($packageid)) ? eval($code) : null; rmdirr($tdir); unset($archive); if ($del > 0) { $filesystem->unlink($sourcefile); } if ($confirm) { echo head(); ok('admin.php?action=packages&job=package_info&id=' . $packageid, $lang->phrase('admin_packages_ok_package_successfully_imported')); } } } elseif ($job == 'package_export') {
} if (isset($ini['template']) && count($ini['template']) > 0) { $desobj = $scache->load('loaddesign'); $designs = $desobj->get(true); $tplid = $designs[$config['templatedir']]['template']; $tpldir = "templates/{$tplid}/modules/{$packageid}/"; if (file_exists($tpldir)) { $filesystem->chmod($tpldir, 0777); } else { $filesystem->mkdir($tpldir, 0777); } $temptpldir = "{$tempdir}templates/"; copyr($temptpldir, $tpldir); rmdirr($temptpldir); } copyr($tempdir, $dir); if (isset($ini['language']) && count($ini['language']) > 0) { $result = $db->query("SELECT id FROM {$db->pre}language", __LINE__, __FILE__); while ($row = $db->fetch_assoc($result)) { $c->getdata("language/{$row['id']}/modules.lng.php", 'lang'); foreach ($ini['language'] as $varname => $text) { $c->updateconfig($varname, str, $text); } $c->savedata(); } } if (isset($ini['php']) && count($ini['php']) > 0) { foreach ($ini['php'] as $hook => $plugfile) { if (isInvisibleHook($hook)) { continue; }
<tr> <td class="ubox" colspan="2" align="center"><input type="submit" name="Submit" value="Copy" /></td> </tr> </table> </form> <?php echo foot(); } elseif ($job == 'lang_copy2') { echo head(); $id = $gpc->get('id', int); $name = $gpc->get('name', str); $desc = $gpc->get('desc', str); $db->query("INSERT INTO {$db->pre}language (language, detail) VALUES ('{$name}', '{$desc}')"); $newid = $db->insert_id(); $filesystem->mkdir("language/{$newid}/", 0755); copyr("language/{$id}/", "language/{$newid}/"); $delobj = $scache->load('loadlanguage'); $delobj->delete(); ok('admin.php?action=language&job=manage', 'Languagepack has been copied successful.'); } elseif ($job == 'lang_delete') { echo head(); $id = $gpc->get('id', int); ?> <table class="border" border="0" cellspacing="0" cellpadding="4"> <tr><td class="obox">Delete languagepack</td></tr> <tr><td class="mbox"> <p align="center">Would you really like to delete this language pack?</p> <p align="center"> <a href="admin.php?action=language&job=lang_delete2&id=<?php echo $id; ?>
function copyr($source, $dest) { // Simple copy for a file if (is_file($source)) { $c = copy($source, $dest); chmod($dest, 0777); return $c; } // Make destination directory if (!is_dir($dest)) { $oldumask = umask(0); mkdir($dest, 0777); umask($oldumask); } // Loop through the folder $dir = dir($source); while (false !== ($entry = $dir->read())) { // Skip pointers if ($entry == "." || $entry == "..") { continue; } // Deep copy directories if ($dest !== "{$source}/{$entry}") { copyr("{$source}/{$entry}", "{$dest}/{$entry}"); } } // Clean up $dir->close(); return true; }
/** * Copies the contents of a directory to the standalone directory */ function make_dir_standalone($dir) { return copyr($dir, 'standalone/' . $dir); }
function exportSite() { global $strBaseFolder, $strZipFolder, $strZipName, $objZip; $objCms = PCMS_Client::getInstance(); $objCms->setLanguage(ContentLanguage::getDefault()); //*** Get a collection of Languages. $objLanguages = $objCms->getLanguages(); foreach ($objLanguages as $objLanguage) { //*** Export the entry page. exportIndexPage($objLanguage); //*** Get the list of pages. $objElements = $objCms->getPageElements($objLanguage->getId()); foreach ($objElements as $objElement) { exportPage($objElement, $objLanguage); } } //*** Export auxilary fodlers. $arrFileFilter = array("js", "css", "jpg", "gif", "png", "ico", "txt", "html"); copyr($strBaseFolder . "css", "css", $arrFileFilter); copyr($strBaseFolder . "includes", "includes", $arrFileFilter); copyr($strBaseFolder . "images", "images", $arrFileFilter); copyr($strBaseFolder . "files", "files", $arrFileFilter); copyr($strBaseFolder . "libraries", "libraries", $arrFileFilter); copyr($strBaseFolder . "favicon.ico", "favicon.ico"); copyr($strBaseFolder . "robots.txt", "robots.txt"); //*** Close zip file. $objZip->save(); //*** Return the zip file to the user. header("HTTP/1.1 200 OK"); header("Pragma: public"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: private", false); header('Content-Type: application/octetstream; charset=utf-8'); header("Content-Length: " . (string) filesize($strZipName)); header('Content-Disposition: attachment; filename="' . $objCms->getAccount()->getUri() . '.zip"'); header("Content-Transfer-Encoding: binary\n"); readfile($strZipName); exit; }
/** * Exports the learning path as a SCORM package. This is the main function that * gathers the content, transforms it, writes the imsmanifest.xml file, zips the * whole thing and returns the zip. * * This method needs to be called in PHP5, as it will fail with non-adequate * XML package (like the ones for PHP4), and it is *not* a static method, so * you need to call it on a learnpath object. * @TODO The method might be redefined later on in the scorm class itself to avoid * creating a SCORM structure if there is one already. However, if the initial SCORM * path has been modified, it should use the generic method here below. * @TODO link this function with the export_lp() function in the same class * @param string Optional name of zip file. If none, title of learnpath is * domesticated and trailed with ".zip" * @return string Returns the zip package string, or null if error */ function scorm_export() { global $_course; global $charset; if (!class_exists('DomDocument')) { error_log('DOM functions not supported for PHP version below 5.0', 0); $this->error = 'PHP DOM functions not supported for PHP versions below 5.0'; return null; } //remove memory and time limits as much as possible as this might be a long process... if (function_exists('ini_set')) { $mem = ini_get('memory_limit'); if (substr($mem, -1, 1) == 'M') { $mem_num = substr($mem, 0, -1); if ($mem_num < 128) { ini_set('memory_limit', '128M'); } } else { ini_set('memory_limit', '128M'); } ini_set('max_execution_time', 600); //}else{ //error_log('Scorm export: could not change memory and time limits',0); } //Create the zip handler (this will remain available throughout the method) $archive_path = api_get_path(SYS_ARCHIVE_PATH); $sys_course_path = api_get_path(SYS_COURSE_PATH); $temp_dir_short = uniqid(); $temp_zip_dir = $archive_path . "/" . $temp_dir_short; $temp_zip_file = $temp_zip_dir . "/" . md5(time()) . ".zip"; $zip_folder = new PclZip($temp_zip_file); $current_course_path = api_get_path(SYS_COURSE_PATH) . api_get_course_path(); $root_path = $main_path = api_get_path(SYS_PATH); $files_cleanup = array(); //place to temporarily stash the zipfiles //create the temp dir if it doesn't exist //or do a cleanup befor creating the zipfile if (!is_dir($temp_zip_dir)) { mkdir($temp_zip_dir); } else { //cleanup: check the temp dir for old files and delete them $handle = opendir($temp_zip_dir); while (false !== ($file = readdir($handle))) { if ($file != "." && $file != "..") { unlink("{$temp_zip_dir}/{$file}"); } } closedir($handle); } $zip_files = $zip_files_abs = $zip_files_dist = array(); if (is_dir($current_course_path . '/scorm/' . $this->path) && is_file($current_course_path . '/scorm/' . $this->path . '/imsmanifest.xml')) { // remove the possible . at the end of the path $dest_path_to_lp = substr($this->path, -1) == '.' ? substr($this->path, 0, -1) : $this->path; $dest_path_to_scorm_folder = str_replace('//', '/', $temp_zip_dir . '/scorm/' . $dest_path_to_lp); $perm = api_get_setting('permissions_for_new_directories'); $perm = octdec(!empty($perm) ? $perm : '0770'); mkdir($dest_path_to_scorm_folder, $perm, 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) //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', $this->encoding); $root = $xmldoc->createElement('manifest'); $root->setAttribute('identifier', 'SingleCourseManifest'); $root->setAttribute('version', '1.1'); $root->setAttribute('xmlns', 'http://www.imsproject.org/xsd/imscp_rootv1p1p2'); $root->setAttribute('xmlns:adlcp', 'http://www.adlnet.org/xsd/adlcp_rootv1p2'); $root->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $root->setAttribute('xsi:schemaLocation', 'http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd'); //Build mandatory sub-root container elements $metadata = $xmldoc->createElement('metadata'); $md_schema = $xmldoc->createElement('schema', 'ADL SCORM'); $metadata->appendChild($md_schema); $md_schemaversion = $xmldoc->createElement('schemaversion', '1.2'); $metadata->appendChild($md_schemaversion); $root->appendChild($metadata); $organizations = $xmldoc->createElement('organizations'); $resources = $xmldoc->createElement('resources'); //Build the only organization we will use in building our learnpaths $organizations->setAttribute('default', 'dokeos_scorm_export'); $organization = $xmldoc->createElement('organization'); $organization->setAttribute('identifier', 'dokeos_scorm_export'); //to set the title of the SCORM entity (=organization), we take the name given //in Dokeos and convert it to HTML entities using the Dokeos charset (not the //learning path charset) as it is the encoding that defines how it is stored //in the database. Then we convert it to HTML entities again as the "&" character //alone is not authorized in XML (must be &) //The title is then decoded twice when extracting (see scorm::parse_manifest) $org_title = $xmldoc->createElement('title', htmlentities(api_htmlentities($this->get_name(), ENT_QUOTES, $charset))); $organization->appendChild($org_title); //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(); 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 { $inc_docs = $item->get_resources_from_source(); } //give a child element <item> to the <organization> element $my_item_id = $item->get_id(); $my_item = $xmldoc->createElement('item'); $my_item->setAttribute('identifier', 'ITEM_' . $my_item_id); $my_item->setAttribute('identifierref', 'RESOURCE_' . $my_item_id); $my_item->setAttribute('isvisible', 'true'); //give a child element <title> to the <item> element $my_title = $xmldoc->createElement('title', htmlspecialchars($item->get_title(), ENT_QUOTES, $this->encoding)); $my_item->appendChild($my_title); //give a child element <adlcp:prerequisites> to the <item> element $my_prereqs = $xmldoc->createElement('adlcp:prerequisites', $this->get_scorm_prereq_string($my_item_id)); $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 hits parent if there is one if (!empty($item->parent) && $item->parent != 0) { $children = $organization->childNodes; $possible_parent =& $this->get_scorm_xml_node($children, 'ITEM_' . $item->parent); if (is_object($possible_parent)) { $possible_parent->appendChild($my_item); } else { if ($this->debug > 0) { error_log('Parent ITEM_' . $item->parent . ' of item ITEM_' . $my_item_id . ' not found'); } } } else { if ($this->debug > 0) { error_log('No parent'); } $organization->appendChild($my_item); } //get the path of the file(s) from the course directory root $my_file_path = $item->get_file_path('scorm/' . $this->path . '/'); $my_xml_file_path = api_htmlentities($my_file_path, ENT_QUOTES, $this->encoding); $my_sub_dir = dirname($my_file_path); $my_xml_sub_dir = api_htmlentities($my_sub_dir, ENT_QUOTES, $this->encoding); //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' if ($item->type == 'sco') { $my_resource->setAttribute('adlcp:scormtype', 'sco'); } else { $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); //dependency to other files - not yet supported $i = 1; foreach ($inc_docs as $doc_info) { if (count($doc_info) < 1 or 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 $abs_path = api_get_path(SYS_PATH) . str_replace(api_get_path(WEB_PATH), '', $doc_info[0]); $current_dir = dirname($abs_path); $file_path = realpath($abs_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 dokeos root path //reduce file path to what's under the DocumentRoot $file_path = substr($file_path, strlen($root_path) - 1); //echo $file_path;echo '<br><br>'; //error_log(__LINE__.'Reduced url 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', $file_path); $my_dep->setAttribute('xml:base', ''); } else { if (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' => $file_path); $my_dep_file->setAttribute('href', $file_path); $my_dep->setAttribute('xml:base', ''); } } } break; case 'abs': //absolute path from DocumentRoot. Save file and leave path as is in the zip $my_dep_file->setAttribute('href', $doc_info[0]); $my_dep->setAttribute('xml:base', ''); //$current_dir = dirname($current_course_path.'/'.$item->get_file_path()).'/'; //the next lines fix a bug when using the "subdir" mode of Dokeos, whereas //an image path would be constructed as /var/www/subdir/subdir/img/foo.bar $abs_img_path_without_subdir = $doc_info[0]; $relp = api_get_path(REL_PATH); //the url-append config param $pos = strpos($abs_img_path_without_subdir, $relp); if ($pos === 0) { $abs_img_path_without_subdir = '/' . substr($abs_img_path_without_subdir, strlen($relp)); } //$file_path = realpath(api_get_path(SYS_PATH).$doc_info[0]); $file_path = realpath(api_get_path(SYS_PATH) . $abs_img_path_without_subdir); $file_path = str_replace('\\', '/', $file_path); $file_path = str_replace('//', '/', $file_path); //error_log(__LINE__.'Abs path: '.$file_path,0); //prepare the current directory path (until just under 'document') with a trailing slash $cur_path = substr($current_course_path, -1) == '/' ? $current_course_path : $current_course_path . '/'; //check if the current document is in that path if (strstr($file_path, $cur_path) !== false) { //the document is in that path, now get the relative path //to the containing document $orig_file_path = dirname($cur_path . $my_file_path) . '/'; $relative_path = ''; if (strstr($file_path, $cur_path) !== false) { $relative_path = substr($file_path, strlen($orig_file_path)); $file_path = substr($file_path, strlen($cur_path)); } else { //this case is still a problem as it's difficult to calculate a relative path easily //might still generate wrong links //$file_path = substr($file_path,strlen($cur_path)); //calculate the directory path to the current file (without trailing slash) $my_relative_path = dirname($file_path); $my_relative_file = basename($file_path); //calculate the directory path to the containing file (without trailing slash) $my_orig_file_path = substr($orig_file_path, 0, -1); $dotdot = ''; $subdir = ''; while (strstr($my_relative_path, $my_orig_file_path) === false && strlen($my_orig_file_path) > 1 && strlen($my_relative_path) > 1) { $my_relative_path2 = dirname($my_relative_path); $my_orig_file_path = dirname($my_orig_file_path); $subdir = substr($my_relative_path, strlen($my_relative_path2) + 1) . "/" . $subdir; $dotdot += '../'; $my_relative_path = $my_relative_path2; } $relative_path = $dotdot . $subdir . $my_relative_file; } //put the current document in the zip (this array is the array //that will manage documents already in the course folder - relative) $zip_files[] = $file_path; //update the links to the current document in the containing document (make them relative) $link_updates[$my_file_path][] = array('orig' => $doc_info[0], 'dest' => $relative_path); $my_dep_file->setAttribute('href', $file_path); $my_dep->setAttribute('xml:base', ''); } elseif (strstr($file_path, $main_path) !== false) { //the calculated real path is really inside the dokeos 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', ''); } else { if (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 $current_dir = dirname($current_course_path . '/' . $item->get_file_path()) . '/'; $file_path = realpath($current_dir . $doc_info[0]); //error_log($file_path.' <-> '.$main_path,0); if (strstr($file_path, $main_path) !== false) { //the calculated real path is really inside the dokeos root path //reduce file path to what's under the DocumentRoot $file_path = substr($file_path, strlen($root_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); $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]); $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_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 if ($item->type == 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 <title> to the <item> element $my_title = $xmldoc->createElement('title', htmlspecialchars($item->get_title(), ENT_QUOTES)); $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 id=' . $item->path; $rs = Database::query($sql, __FILE__, __LINE__); 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($my_file_path, ENT_QUOTES, $this->encoding); $my_sub_dir = dirname($my_file_path); $my_xml_sub_dir = api_htmlentities($my_sub_dir, ENT_QUOTES, $this->encoding); //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); } } elseif ($item->type == 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($item->get_title(), ENT_QUOTES, $this->encoding)); $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($my_file_path, ENT_QUOTES, $this->encoding); $my_sub_dir = dirname($my_file_path); $my_xml_sub_dir = api_htmlentities($my_sub_dir, ENT_QUOTES, $this->encoding); //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 or 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); $file_path = realpath($abs_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 dokeos 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', ''); } else { if (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()) . '/'; $file_path = realpath($doc_info[0]); $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 dokeos 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', ''); } else { if (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 $current_dir = dirname($current_course_path . '/' . $item->get_file_path()) . '/'; $file_path = realpath($current_dir . $doc_info[0]); //error_log($file_path.' <-> '.$main_path,0); if (strstr($file_path, $main_path) !== false) { //the calculated real path is really inside the dokeos 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/DOKEOS/document/.... $info_file_path = explode('/', $file_path); if ($info_file_path[0] == 'courses') { //add character "/" in file path $file_path_dest = '/' . $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++; } $resources->appendChild($my_resource); $zip_files[] = $my_file_path; } else { //get the path of the file(s) from the course directory root $my_file_path = 'non_exportable.html'; $my_xml_file_path = api_htmlentities($my_file_path, ENT_COMPAT, $this->encoding); $my_sub_dir = dirname($my_file_path); $my_xml_sub_dir = api_htmlentities($my_sub_dir, ENT_COMPAT, $this->encoding); //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', 'document/' . $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); } } } $organizations->appendChild($organization); $root->appendChild($organizations); $root->appendChild($resources); $xmldoc->appendChild($root); //todo: add a readme file here, with a short description and a link to the Reload player //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); $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 // ../../.. to return from inc/lib/flv_player to the document/main path if (substr($old_new['dest'], -3) == 'flv' && substr($old_new['dest'], 0, 5) == 'main/') { $old_new['dest'] = str_replace('main/', '../../../', $old_new['dest']); } elseif (substr($old_new['dest'], -3) == 'flv' && substr($old_new['dest'], 0, 6) == 'video/') { $old_new['dest'] = str_replace('video/', '../../../../video/', $old_new['dest']); } if (substr($old_new['dest'], 0, 1) == '/') { $old_new['dest'] = substr($old_new['dest'], 1); } $string = str_replace($old_new['orig'], $old_new['dest'], $string); $string = str_replace(str_replace('https', 'http', $old_new['orig']), $old_new['dest'], $string); } file_put_contents($dest_file, $string); } } 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); $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 // ../../.. to return from inc/lib/flv_player to the document/main path if (substr($old_new['dest'], -3) == 'flv' && substr($old_new['dest'], 0, 5) == 'main/') { $old_new['dest'] = str_replace('main/', '../../../', $old_new['dest']); } if (substr($old_new['dest'], 0, 1) == '/') { $old_new['dest'] = substr($old_new['dest'], 1); } $string = str_replace($old_new['orig'], $old_new['dest'], $string); $string = str_replace(str_replace('https', 'http', $old_new['orig']), $old_new['dest'], $string); } file_put_contents($dest_file, $string); } } if (is_array($links_to_create)) { foreach ($links_to_create as $file => $link) { $file_content = '<html><body><div style="text-align:center"><a href="' . $link['url'] . '">' . $link['title'] . '</a></div></body></html>'; file_put_contents($archive_path . $temp_dir_short . '/' . $file, $file_content); } } // add non exportable message explanation $lang_not_exportable = get_lang('ThisItemIsNotExportable'); $file_content = <<<EOD <html> \t<head> \t\t<style> \t\t\t.error-message { \t\t\t\tfont-family: arial, verdana, helvetica, sans-serif; \t\t\t\tborder-width: 1px; \t\t\t\tborder-style: solid; \t\t\t\tleft: 50%; \t\t\t\tmargin: 10px auto; \t\t\t\tmin-height: 30px; \t\t\t\tpadding: 5px; \t\t\t\tright: 50%; \t\t\t\twidth: 500px; \t\t\t\tbackground-color: #FFD1D1; \t\t\t\tborder-color: #FF0000; \t\t\t\tcolor: #000; \t\t\t} \t\t</style> \t<body> \t\t<div class="error-message"> \t\t\t{$lang_not_exportable} \t\t</div> \t</body> </html> EOD; if (!is_dir($archive_path . $temp_dir_short . '/document')) { @mkdir($archive_path . $temp_dir_short . '/document'); } file_put_contents($archive_path . $temp_dir_short . '/document/non_exportable.html', $file_content); //Add the extra files that go along with a SCORM package $main_code_path = api_get_path(SYS_CODE_PATH) . 'newscorm/packaging/'; $extra_files = scandir($main_code_path); foreach ($extra_files as $extra_file) { if (strpos($extra_file, '.') === 0) { continue; } else { $dest_file = $archive_path . $temp_dir_short . '/' . $extra_file; $this->create_path($dest_file); copy($main_code_path . $extra_file, $dest_file); } } //Finalize the imsmanifest structure, add to the zip, then return the zip $xmldoc->save($archive_path . '/' . $temp_dir_short . '/imsmanifest.xml'); $zip_folder->add($archive_path . '/' . $temp_dir_short, PCLZIP_OPT_REMOVE_PATH, $archive_path . '/' . $temp_dir_short . '/'); //clean possible temporary files foreach ($files_cleanup as $file) { $res = unlink($file); 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 = preg_replace('([^a-zA-Z0-9_\\.])', '-', html_entity_decode($this->get_name(), ENT_QUOTES)) . '.zip'; DocumentManager::file_send_for_download($temp_zip_file, true, $name); }
function copyFolder($oldName, $newName) { if($oldName == $newName) return true; $base = $this->getBaseDir(); if(!copyr($base . $oldName, $base . $newName)) { $this->error("Couldn't rename $base$oldName to $base$newName"); return false; } else { return true; } }