/**
  * Restore a course.
  * @param 	string 	The code of the Chamilo-course in
  * @param	int		The session id
  * @param	bool	Course settings are going to be restore?
  */
 public function restore($destination_course_code = '', $session_id = 0, $update_course_settings = false, $respect_base_content = false)
 {
     if ($destination_course_code == '') {
         $course_info = api_get_course_info();
         $this->destination_course_info = $course_info;
         $this->course->destination_path = $course_info['path'];
     } else {
         $course_info = api_get_course_info($destination_course_code);
         $this->destination_course_info = $course_info;
         $this->course->destination_path = $course_info['path'];
     }
     $this->destination_course_id = $course_info['real_id'];
     //Getting first teacher (for the forums)
     $teacher_list = CourseManager::get_teacher_list_from_course_code($course_info['real_id']);
     $this->first_teacher_id = api_get_user_id();
     if (!empty($teacher_list)) {
         foreach ($teacher_list as $teacher) {
             $this->first_teacher_id = $teacher['user_id'];
             break;
         }
     }
     if (empty($this->course)) {
         return false;
     }
     // Source platform encoding - reading/detection
     // The correspondent data field has been added as of version 1.8.6.1
     if (empty($this->course->encoding)) {
         // The archive has been created by a system which is prior to 1.8.6.1 version.
         // In this case we have to detect the encoding.
         $sample_text = $this->course->get_sample_text() . "\n";
         // Let us exclude ASCII lines, probably they are English texts.
         $sample_text = explode("\n", $sample_text);
         foreach ($sample_text as $key => &$line) {
             if (api_is_valid_ascii($line)) {
                 unset($sample_text[$key]);
             }
         }
         $sample_text = join("\n", $sample_text);
         $this->course->encoding = api_detect_encoding($sample_text, $course_info['language']);
     }
     // Encoding conversion of the course, if it is needed.
     $this->course->to_system_encoding();
     foreach ($this->tools_to_restore as $tool) {
         $function_build = 'restore_' . $tool;
         $this->{$function_build}($session_id, $respect_base_content, $destination_course_code);
     }
     if ($update_course_settings) {
         $this->restore_course_settings($destination_course_code);
     }
     // Restore the item properties
     $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
     $condition_session = "";
     if (!empty($session_id)) {
         $condition_session = " , id_session='" . intval($session_id) . "'";
     }
     foreach ($this->course->resources as $type => $resources) {
         if (is_array($resources)) {
             foreach ($resources as $id => $resource) {
                 foreach ($resource->item_properties as $property) {
                     // First check if there isn't allready a record for this resource
                     $sql = "SELECT * FROM {$table} WHERE c_id = " . $this->destination_course_id . " AND tool = '" . $property['tool'] . "' AND ref = '" . $resource->destination_id . "'";
                     $res = Database::query($sql);
                     if (Database::num_rows($res) == 0) {
                         // The to_group_id and to_user_id are set to default values as users/groups possibly not exist in the target course
                         $sql = "INSERT INTO {$table} SET\n\t\t\t\t\t\t\t\t\tc_id \t\t\t\t= '" . $this->destination_course_id . "',\n\t\t\t\t\t\t\t\t\ttool \t\t\t\t= '" . self::DBUTF8escapestring($property['tool']) . "',\n\t\t\t\t\t\t\t\t\tinsert_user_id \t\t= '" . self::DBUTF8escapestring($property['insert_user_id']) . "',\n\t\t\t\t\t\t\t\t\tinsert_date \t\t= '" . self::DBUTF8escapestring($property['insert_date']) . "',\n\t\t\t\t\t\t\t\t\tlastedit_date \t\t= '" . self::DBUTF8escapestring($property['lastedit_date']) . "',\n\t\t\t\t\t\t\t\t\tref \t\t\t\t= '" . self::DBUTF8escapestring($resource->destination_id) . "',\n\t\t\t\t\t\t\t\t\tlastedit_type \t\t= '" . self::DBUTF8escapestring($property['lastedit_type']) . "',\n\t\t\t\t\t\t\t\t\tlastedit_user_id \t= '" . self::DBUTF8escapestring($property['lastedit_user_id']) . "',\n\t\t\t\t\t\t\t\t\tvisibility \t\t\t= '" . self::DBUTF8escapestring($property['visibility']) . "',\n\t\t\t\t\t\t\t\t\tstart_visible \t\t= '" . self::DBUTF8escapestring($property['start_visible']) . "',\n\t\t\t\t\t\t\t\t\tend_visible \t\t= '" . self::DBUTF8escapestring($property['end_visible']) . "',\n\t\t\t\t\t\t\t\t\tto_user_id  \t\t= '" . self::DBUTF8escapestring($property['to_user_id']) . "',\n\t\t\t\t\t\t\t\t\tto_group_id \t\t= '0' {$condition_session}";
                         Database::query($sql);
                     }
                 }
             }
         }
     }
 }
/**
 * Transliterates a string with arbitrary encoding into a plain ASCII string.
 *
 * Example:
 * echo api_transliterate(api_html_entity_decode(
 * 	'Фёдор '.
 * 	'Михайлович '.
 * 	'Достоевкий',
 * 	ENT_QUOTES, 'UTF-8'), 'X', 'UTF-8');
 * The output should be: Fyodor Mihaylovich Dostoevkiy
 *
 * @param string $string					The input string.
 * @param string $unknown (optional)		Replacement character for unknown characters and illegal UTF-8 sequences.
 * @param string $from_encoding (optional)	The encoding of the input string. If it is omited, the platform character set is assumed.
 * @return string							Plain ASCII output.
 *
 * Based on Drupal's module "Transliteration", version 6.x-2.1, 09-JUN-2009:
 * @author Stefan M. Kudwien (smk-ka)
 * @author Daniel F. Kudwien (sun)
 * @link http://drupal.org/project/transliteration
 *
 * See also MediaWiki's UtfNormal.php and CPAN's Text::Unidecode library
 * @link http://www.mediawiki.org
 * @link http://search.cpan.org/~sburke/Text-Unidecode-0.04/lib/Text/Unidecode.pm).
 *
 * Adaptation for Chamilo 1.8.7, 2010
 * Initial implementation for Dokeos 1.8.6.1, 12-JUN-2009
 * @author Ivan Tcholakov
 */
function api_transliterate($string, $unknown = '?', $from_encoding = null)
{
    static $map = array();
    $string = api_utf8_encode($string, $from_encoding);
    // Screen out some characters that eg won't be allowed in XML.
    $string = preg_replace('/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/', $unknown, $string);
    // ASCII is always valid NFC!
    // If we're only ever given plain ASCII, we can avoid the overhead
    // of initializing the decomposition tables by skipping out early.
    if (api_is_valid_ascii($string)) {
        return $string;
    }
    static $tail_bytes;
    if (!isset($tail_bytes)) {
        // Each UTF-8 head byte is followed by a certain
        // number of tail bytes.
        $tail_bytes = array();
        for ($n = 0; $n < 256; $n++) {
            if ($n < 0xc0) {
                $remaining = 0;
            } elseif ($n < 0xe0) {
                $remaining = 1;
            } elseif ($n < 0xf0) {
                $remaining = 2;
            } elseif ($n < 0xf8) {
                $remaining = 3;
            } elseif ($n < 0xfc) {
                $remaining = 4;
            } elseif ($n < 0xfe) {
                $remaining = 5;
            } else {
                $remaining = 0;
            }
            $tail_bytes[chr($n)] = $remaining;
        }
    }
    // Chop the text into pure-ASCII and non-ASCII areas;
    // large ASCII parts can be handled much more quickly.
    // Don't chop up Unicode areas for punctuation, though,
    // that wastes energy.
    preg_match_all('/[\\x00-\\x7f]+|[\\x80-\\xff][\\x00-\\x40\\x5b-\\x5f\\x7b-\\xff]*/', $string, $matches);
    $result = '';
    foreach ($matches[0] as $str) {
        if ($str[0] < "€") {
            // ASCII chunk: guaranteed to be valid UTF-8
            // and in normal form C, so skip over it.
            $result .= $str;
            continue;
        }
        // We'll have to examine the chunk byte by byte to ensure
        // that it consists of valid UTF-8 sequences, and to see
        // if any of them might not be normalized.
        //
        // Since PHP is not the fastest language on earth, some of
        // this code is a little ugly with inner loop optimizations.
        $head = '';
        $chunk = api_byte_count($str);
        // Counting down is faster. I'm *so* sorry.
        $len = $chunk + 1;
        for ($i = -1; --$len;) {
            $c = $str[++$i];
            if ($remaining = $tail_bytes[$c]) {
                // UTF-8 head byte!
                $sequence = $head = $c;
                do {
                    // Look for the defined number of tail bytes...
                    if (--$len && ($c = $str[++$i]) >= "€" && $c < "À") {
                        // Legal tail bytes are nice.
                        $sequence .= $c;
                    } else {
                        if ($len == 0) {
                            // Premature end of string!
                            // Drop a replacement character into output to
                            // represent the invalid UTF-8 sequence.
                            $result .= $unknown;
                            break 2;
                        } else {
                            // Illegal tail byte; abandon the sequence.
                            $result .= $unknown;
                            // Back up and reprocess this byte; it may itself
                            // be a legal ASCII or UTF-8 sequence head.
                            --$i;
                            ++$len;
                            continue 2;
                        }
                    }
                } while (--$remaining);
                $n = ord($head);
                if ($n <= 0xdf) {
                    $ord = ($n - 192) * 64 + (ord($sequence[1]) - 128);
                } else {
                    if ($n <= 0xef) {
                        $ord = ($n - 224) * 4096 + (ord($sequence[1]) - 128) * 64 + (ord($sequence[2]) - 128);
                    } else {
                        if ($n <= 0xf7) {
                            $ord = ($n - 240) * 262144 + (ord($sequence[1]) - 128) * 4096 + (ord($sequence[2]) - 128) * 64 + (ord($sequence[3]) - 128);
                        } else {
                            if ($n <= 0xfb) {
                                $ord = ($n - 248) * 16777216 + (ord($sequence[1]) - 128) * 262144 + (ord($sequence[2]) - 128) * 4096 + (ord($sequence[3]) - 128) * 64 + (ord($sequence[4]) - 128);
                            } else {
                                if ($n <= 0xfd) {
                                    $ord = ($n - 252) * 1073741824 + (ord($sequence[1]) - 128) * 16777216 + (ord($sequence[2]) - 128) * 262144 + (ord($sequence[3]) - 128) * 4096 + (ord($sequence[4]) - 128) * 64 + (ord($sequence[5]) - 128);
                                }
                            }
                        }
                    }
                }
                // Lookup and replace a character from the transliteration database.
                $bank = $ord >> 8;
                // Check if we need to load a new bank
                if (!isset($map[$bank])) {
                    $file = dirname(__FILE__) . '/internationalization_database/transliteration/' . sprintf('x%02x', $bank) . '.php';
                    if (file_exists($file)) {
                        $map[$bank] = (include $file);
                    } else {
                        $map[$bank] = array('en' => array());
                    }
                }
                $ord = $ord & 255;
                $result .= isset($map[$bank]['en'][$ord]) ? $map[$bank]['en'][$ord] : $unknown;
                $head = '';
            } elseif ($c < "€") {
                // ASCII byte.
                $result .= $c;
                $head = '';
            } elseif ($c < "À") {
                // Illegal tail bytes.
                if ($head == '') {
                    $result .= $unknown;
                }
            } else {
                // Miscellaneous freaks.
                $result .= $unknown;
                $head = '';
            }
        }
    }
    return $result;
}