Browse Source

Merge branch '1.10.x' of github.com:chamilo/chamilo-lms into 1.10.x

Yannick Warnier 9 years ago
parent
commit
d46921717e
64 changed files with 2086 additions and 9378 deletions
  1. 117 5
      app/Resources/public/css/base.css
  2. 3 2
      main/admin/group_list.php
  3. 1 1
      main/admin/user_list.php
  4. 6 2
      main/document/create_audio.php
  5. 46 44
      main/exercice/exercise_result.class.php
  6. 2 1
      main/exercice/export/aiken/aiken_import.inc.php
  7. 1 1
      main/exercice/hotpotatoes.lib.php
  8. 38 35
      main/exercice/hotpotatoes_exercise_result.class.php
  9. 10 8
      main/exercice/savescores.php
  10. 10 5
      main/gradebook/lib/GradebookUtils.php
  11. 38 30
      main/gradebook/lib/be/abstractlink.class.php
  12. 22 11
      main/gradebook/lib/be/evaluation.class.php
  13. 13 13
      main/gradebook/lib/gradebook_result.class.php
  14. 12 10
      main/gradebook/lib/scoredisplay.class.php
  15. BIN
      main/img/icons/64/plugins.png
  16. 9 7
      main/inc/global.inc.php
  17. 46 33
      main/inc/lib/api.lib.php
  18. 181 12
      main/inc/lib/course.lib.php
  19. 13 1
      main/inc/lib/database.lib.php
  20. 9 13
      main/inc/lib/document.lib.php
  21. 11 11
      main/inc/lib/events.lib.php
  22. 21 19
      main/inc/lib/groupmanager.lib.php
  23. 93 93
      main/inc/lib/javascript/chat/js/chat.js
  24. 35 15
      main/inc/lib/message.lib.php
  25. 1 1
      main/inc/lib/online.inc.php
  26. 0 104
      main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer.php
  27. 0 261
      main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/BIFFwriter.php
  28. 0 1114
      main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Format.php
  29. 0 1703
      main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Parser.php
  30. 0 230
      main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Validator.php
  31. 0 1591
      main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Workbook.php
  32. 0 3534
      main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Worksheet.php
  33. 0 6
      main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/index.html
  34. 0 6
      main/inc/lib/pear/Spreadsheet_Excel_Writer/index.html
  35. 426 17
      main/inc/lib/sessionmanager.lib.php
  36. 5 1
      main/inc/lib/social.lib.php
  37. 50 42
      main/inc/lib/system_announcements.lib.php
  38. 4 2
      main/inc/lib/template.lib.php
  39. 1 1
      main/inc/lib/text.lib.php
  40. 49 25
      main/inc/lib/thematic.lib.php
  41. 367 0
      main/inc/lib/userportal.lib.php
  42. 2 0
      main/install/configuration.dist.php
  43. 1 1
      main/lang/dutch/trad4all.inc.php
  44. 2 2
      main/lang/english/trad4all.inc.php
  45. 17 26
      main/mySpace/current_courses.php
  46. 10 7
      main/newscorm/learnpath.class.php
  47. 1 1
      main/newscorm/lp_admin_view.php
  48. 4 3
      main/newscorm/openoffice_document.class.php
  49. 4 3
      main/newscorm/openoffice_presentation.class.php
  50. 49 16
      main/newscorm/openoffice_text.class.php
  51. 11 10
      main/newscorm/openoffice_text_document.class.php
  52. 23 15
      main/session/resume_session.php
  53. 30 26
      main/social/profile.php
  54. 68 26
      main/survey/survey.lib.php
  55. 19 0
      main/template/default/layout/footer.tpl
  56. 1 0
      main/template/default/layout/page_body.tpl
  57. 17 57
      main/tracking/course_session_report.php
  58. 32 11
      main/tracking/exams.php
  59. 39 66
      main/tracking/lp_results_by_user.php
  60. 0 41
      main/tracking/question_course_report.php
  61. 1 1
      main/user/subscribe_user.php
  62. 9 5
      src/Chamilo/CoreBundle/Entity/Repository/SequenceRepository.php
  63. 6 9
      src/Chamilo/CoreBundle/Entity/Repository/SessionRepository.php
  64. 100 42
      user_portal.php

+ 117 - 5
app/Resources/public/css/base.css

@@ -1,11 +1,12 @@
 /*
     Theme Name: Chamilo Base
     URI Project: http://www.chamilo.org
-	  Description: Styles main base of Chamilo LMS appearance , works with Bootstrap 3.0.x
-    Author: alex.aragon@beeznest.com
-            angel.quiroz@beeznest.com
-            julio.montoya@beeznest.com
-            yannik.warnier@beeznest.com
+    Description: Styles main base of Chamilo LMS appearance, works with Bootstrap 3.0.x
+    Author:
+        alex.aragon@beeznest.com
+        angel.quiroz@beeznest.com
+        julio.montoya@beeznest.com
+        yannik.warnier@beeznest.com
     Version: 1.0
 */
 pre {
@@ -6179,6 +6180,117 @@ div#chat-remote-video video {
 .filler-report .filler-report-data-init{
   width: 60%;
 }
+
+
+
+/* CSS for the view by session My Course tab */
+.session-view-block {
+    font-size : 14px;
+    font-weight : normal;
+}
+
+.session-view-row {
+    padding: 8px 0;
+}
+
+.session-view-lvl-2 {
+    margin-left : 66px;
+}
+
+.session-view-lvl-3 {
+    padding-left : 92px;
+}
+
+.session-view-lvl-4 {
+    padding-left : 102px;
+}
+
+.session-view-lvl-5 {
+    padding-left : 128px;
+    font-weight : normal;
+}
+
+.session-view-lvl-6 {
+    padding-left : 20px;
+}
+
+.session-view-lvl-7 {
+    padding-left : 48px;
+}
+
+img.sessionView {
+    padding-right: 10px;
+}
+
+a.sessionView {
+    font-weight : bold;
+}
+
+.session-view-user-category {
+    font-weight : bold;
+    padding-bottom : 10px;
+}
+
+.session-view-session-category {
+    font-weight : bold;
+    padding-bottom : 10px;
+}
+
+.session-view-session {
+    font-weight : bold;
+}
+
+/* Like the well class */
+.session-view-well {
+    min-height: 20px;
+    padding: 19px;
+    margin-bottom: 20px;
+    background-color: #F5F5F5;
+    border: 1px solid rgba(0, 0, 0, 0.05);
+    border-radius: 4px;
+    box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.05) inset;
+}
+
+.session-view-button {
+    border : none;
+    min-width : 28px;
+}
+
+.view-by-session-link {
+    min-height: 38px;
+}
+
+.view-by-session-teachers {
+    display : none; /* change this if you want to display teachers name in this view */
+    font-size : 10px;
+    overflow-x : auto;
+    overflow-y: auto;
+    max-height:50px;
+}
+
+.view-by-session-right-actions {
+    float : right;
+}
+
+.view-by-session-right-actions img {
+    width : 12px;
+}
+
+.session-view-session-go-to-course-in-session {
+    font-size : 12px;
+}
+
+#gradebook_list .centered {
+    text-align:center;
+    vertical-align:middle;
+}
+
+#gradebook_list .centered .badge-group {
+    width: auto;
+}
+
+
+
 /* CSS NEW TOP ******************************************************************************/
 /* CSS Responsive */
 @media (min-width: 1025px) and (max-width: 1200px) {

+ 3 - 2
main/admin/group_list.php

@@ -208,8 +208,9 @@ function modify_filter($group_id, $url_params, $row) {
  * @param string $url_params
  * @return string Some HTML-code with the lock/unlock button
  */
-function active_filter($active, $url_params, $row) {
-    global $_user;
+function active_filter($active, $url_params, $row)
+{
+    $_user = api_get_user_info();
 
     if ($active == '1') {
         $action = 'lock';

+ 1 - 1
main/admin/user_list.php

@@ -602,7 +602,7 @@ function modify_filter($user_id, $url_params, $row) {
  */
 function active_filter($active, $params, $row)
 {
-	global $_user;
+    $_user = api_get_user_info();
 
     if ($active == '1') {
         $action = 'Lock';

+ 6 - 2
main/document/create_audio.php

@@ -357,7 +357,10 @@ function downloadMP3_google($filepath, $dir)
 		echo '<script>window.location.href="'.$location.'"</script>';
 		return;
 	}
-    global $_course, $_user;
+
+	$_course = api_get_course_info();
+	$_user = api_get_user_info();
+
 	$clean_title=trim($_POST['title']);
 	$clean_text=trim($_POST['text']);
 	if(empty($clean_title) || empty($clean_text)){
@@ -464,7 +467,8 @@ function downloadMP3_pediaphon($filepath, $dir)
 		echo '<script>window.location.href="'.$location.'"</script>';
 		return;
 	}
-    global $_course, $_user;
+	$_course = api_get_course_info();
+	$_user = api_get_user_info();
 	$clean_title=trim($_POST['title']);
 	$clean_title= Database::escape_string($clean_title);
 	$clean_text=trim($_POST['text']);

+ 46 - 44
main/exercice/exercise_result.class.php

@@ -409,17 +409,15 @@ class ExerciseResult
     ) {
 		global $charset;
 		$this->getExercisesReporting($document_path, $user_id, $export_filter, $exercise_id, $hotpotato_name);
-		$filename = 'exercise_results_'.date('YmdGis').'.xls';
+		$filename = 'exercise_results_'.api_get_local_time().'.xls';
 		if (!empty($user_id)) {
-			$filename = 'exercise_results_user_'.$user_id.'_'.date('YmdGis').'.xls';
+			$filename = 'exercise_results_user_'.$user_id.'_'.api_get_local_time().'.xls';
 		}
-		$workbook = new Spreadsheet_Excel_Writer();
-		$workbook->setTempDir(api_get_path(SYS_ARCHIVE_PATH));
-		$workbook->setVersion(8); // BIFF8
 
-		$workbook->send($filename);
-		$worksheet =& $workbook->addWorksheet('Report '.date('YmdGis'));
-		$worksheet->setInputEncoding(api_get_system_encoding());
+        $spreadsheet = new PHPExcel();
+        $spreadsheet->setActiveSheetIndex(0);
+        $worksheet = $spreadsheet->getActiveSheet();
+
 		$line = 0;
 		$column = 0; //skip the first column (row titles)
 
@@ -436,26 +434,26 @@ class ExerciseResult
 
 		if ($with_column_user) {
             if (api_is_western_name_order()) {
-    			$worksheet->write($line, $column,get_lang('FirstName'));
+    			$worksheet->SetCellValueByColumnAndRow($line, $column,get_lang('FirstName'));
     			$column++;
-                $worksheet->write($line, $column,get_lang('LastName'));
+                $worksheet->SetCellValueByColumnAndRow($line, $column,get_lang('LastName'));
                 $column++;
             } else {
-                $worksheet->write($line, $column,get_lang('LastName'));
+                $worksheet->SetCellValueByColumnAndRow($line, $column,get_lang('LastName'));
                 $column++;
-                $worksheet->write($line, $column,get_lang('FirstName'));
+                $worksheet->SetCellValueByColumnAndRow($line, $column,get_lang('FirstName'));
                 $column++;
             }
 
             if ($officialCodeInList === 'true') {
-                $worksheet->write($line, $column, get_lang('OfficialCode'));
+                $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('OfficialCode'));
                 $column++;
             }
 
-            $worksheet->write($line, $column, get_lang('Email'));
+            $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('Email'));
 		    $column++;
 		}
-        $worksheet->write($line, $column, get_lang('Groups'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('Groups'));
 	    $column++;
 
 		if ($export_user_fields) {
@@ -464,28 +462,28 @@ class ExerciseResult
 
 			//show the fields names for user fields
 			foreach ($extra_user_fields as $field) {
-				$worksheet->write($line,$column,api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES, $charset));
+				$worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES, $charset));
 				$column++;
 			}
 		}
 
-		$worksheet->write($line, $column, get_lang('Title'));
+		$worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('Title'));
 		$column++;
-		$worksheet->write($line, $column, get_lang('StartDate'));
+		$worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('StartDate'));
         $column++;
-        $worksheet->write($line, $column, get_lang('EndDate'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('EndDate'));
         $column++;
-        $worksheet->write($line, $column, get_lang('Duration').' ('.get_lang('MinMinutes').')');
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('Duration').' ('.get_lang('MinMinutes').')');
 		$column++;
-		$worksheet->write($line, $column, get_lang('Score'));
+		$worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('Score'));
 		$column++;
-		$worksheet->write($line, $column, get_lang('Total'));
+		$worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('Total'));
 		$column++;
-        $worksheet->write($line, $column, get_lang('Status'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('Status'));
 		$column++;
-        $worksheet->write($line, $column, get_lang('ToolLearnpath'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('ToolLearnpath'));
         $column++;
-        $worksheet->write($line, $column, get_lang('UserIsCurrentlySubscribed'));
+        $worksheet->SetCellValueByColumnAndRow($line, $column, get_lang('UserIsCurrentlySubscribed'));
 		$line++;
 
 		foreach ($this->results as $row) {
@@ -493,59 +491,63 @@ class ExerciseResult
 
             if ($with_column_user) {
                 if (api_is_western_name_order()) {
-                    $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['first_name']), ENT_QUOTES, $charset));
+                    $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['first_name']), ENT_QUOTES, $charset));
                     $column++;
-                    $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['last_name']), ENT_QUOTES, $charset));
+                    $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['last_name']), ENT_QUOTES, $charset));
                     $column++;
                 } else {
-                    $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['last_name']), ENT_QUOTES, $charset));
+                    $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['last_name']), ENT_QUOTES, $charset));
                     $column++;
-                    $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['first_name']), ENT_QUOTES, $charset));
+                    $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['first_name']), ENT_QUOTES, $charset));
                     $column++;
                 }
 
                 if ($officialCodeInList === 'true') {
-                    $worksheet->write($line, $column,api_html_entity_decode(strip_tags($row['official_code']), ENT_QUOTES, $charset));
+                    $worksheet->SetCellValueByColumnAndRow($line, $column,api_html_entity_decode(strip_tags($row['official_code']), ENT_QUOTES, $charset));
                     $column++;
                 }
 
-                $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['email']), ENT_QUOTES, $charset));
+                $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['email']), ENT_QUOTES, $charset));
                 $column++;
 			}
 
-            $worksheet->write($line,$column,api_html_entity_decode(strip_tags(implode(", ", GroupManager :: get_user_group_name($row['user_id']))), ENT_QUOTES, $charset));
+            $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags(implode(", ", GroupManager :: get_user_group_name($row['user_id']))), ENT_QUOTES, $charset));
             $column++;
 
 			if ($export_user_fields) {
 				//show user fields data, if any, for this user
 				$user_fields_values = UserManager::get_extra_user_data($row['user_id'],false,false, false, true);
 				foreach($user_fields_values as $value) {
-					$worksheet->write($line,$column, api_html_entity_decode(strip_tags($value), ENT_QUOTES, $charset));
+					$worksheet->SetCellValueByColumnAndRow($line,$column, api_html_entity_decode(strip_tags($value), ENT_QUOTES, $charset));
 					$column++;
 				}
 			}
 
-			$worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['title']), ENT_QUOTES, $charset));
+			$worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['title']), ENT_QUOTES, $charset));
 			$column++;
-            $worksheet->write($line, $column, $row['start_date']);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $row['start_date']);
             $column++;
-            $worksheet->write($line, $column, $row['end_date']);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $row['end_date']);
             $column++;
-            $worksheet->write($line, $column, $row['duration']);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $row['duration']);
             $column++;
-            $worksheet->write($line, $column, $row['result']);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $row['result']);
             $column++;
-            $worksheet->write($line, $column, $row['max']);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $row['max']);
             $column++;
-            $worksheet->write($line, $column, $row['status']);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $row['status']);
             $column++;
-            $worksheet->write($line, $column, $row['lp_name']);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $row['lp_name']);
             $column++;
-            $worksheet->write($line, $column, $row['is_user_subscribed']);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $row['is_user_subscribed']);
 			$line++;
 		}
-		//output the results
-		$workbook->close();
+
+        $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
+        $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
+        $writer->save($file);
+        DocumentManager::file_send_for_download($file, true, $filename);
+
 		return true;
 	}
 }

+ 2 - 1
main/exercice/export/aiken/aiken_import.inc.php

@@ -58,7 +58,8 @@ function aiken_display_form($msg = '') {
  * @return bool True on success, false on failure
  */
 function get_and_unzip_uploaded_exercise($baseWorkDir, $uploadPath) {
-    global $_course, $_user;
+    $_course = api_get_course_info();
+    $_user = api_get_user_info();
     //Check if the file is valid (not to big and exists)
     if (!isset ($_FILES['userFile']) || !is_uploaded_file($_FILES['userFile']['tmp_name'])) {
         // upload failed

+ 1 - 1
main/exercice/hotpotatoes.lib.php

@@ -140,7 +140,7 @@ function ReadFileCont($full_file_path)
 function WriteFileCont($full_file_path, $content)
 {
     // Check if this is not an attack, trying to get into other directories or something like that.
-    global $_course;
+    $_course = api_get_course_info();
     if (Security::check_abs_path(dirname($full_file_path).'/', api_get_path(SYS_COURSE_PATH).$_course['path'].'/')) {
         // Check if this is not an attack, trying to upload a php file or something like that.
         if (basename($full_file_path) != Security::filter_filename(basename($full_file_path))) {

+ 38 - 35
main/exercice/hotpotatoes_exercise_result.class.php

@@ -226,17 +226,16 @@ class HotpotatoesExerciseResult
     ) {
 		global $charset;
 		$this->getExercisesReporting($document_path, $user_id, $export_filter, $exercise_id, $hotpotato_name);
-		$filename = 'exercise_results_'.date('YmdGis').'.xls';
+		$filename = 'exercise_results_'.api_get_local_time().'.xls';
 		if (!empty($user_id)) {
-			$filename = 'exercise_results_user_'.$user_id.'_'.date('YmdGis').'.xls';
+			$filename = 'exercise_results_user_'.$user_id.'_'.api_get_local_time().'.xls';
 		}
-		$workbook = new Spreadsheet_Excel_Writer();
-		$workbook->setTempDir(api_get_path(SYS_ARCHIVE_PATH));
-		$workbook->setVersion(8); // BIFF8
 
-		$workbook->send($filename);
-		$worksheet =& $workbook->addWorksheet('Report '.date('YmdGis'));
-		$worksheet->setInputEncoding(api_get_system_encoding());
+        $spreadsheet = new PHPExcel();
+        $spreadsheet->setActiveSheetIndex(0);
+        $worksheet = $spreadsheet->getActiveSheet();
+
+
 		$line = 0;
 		$column = 0; //skip the first column (row titles)
 
@@ -250,18 +249,18 @@ class HotpotatoesExerciseResult
 		}
 
 		if ($with_column_user) {
-		    $worksheet->write($line,$column,get_lang('Email'));
+		    $worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('Email'));
 		    $column++;
 
             if (api_is_western_name_order()) {
-    			$worksheet->write($line,$column,get_lang('FirstName'));
+    			$worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('FirstName'));
     			$column++;
-                $worksheet->write($line,$column,get_lang('LastName'));
+                $worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('LastName'));
                 $column++;
             } else {
-                $worksheet->write($line,$column,get_lang('LastName'));
+                $worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('LastName'));
                 $column++;
-                $worksheet->write($line,$column,get_lang('FirstName'));
+                $worksheet->SetCellValueByColumnAndRow($line,$column,get_lang('FirstName'));
                 $column++;
             }
 		}
@@ -272,42 +271,42 @@ class HotpotatoesExerciseResult
 
 			//show the fields names for user fields
 			foreach ($extra_user_fields as $field) {
-				$worksheet->write($line, $column, api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES, $charset));
+				$worksheet->SetCellValueByColumnAndRow($line, $column, api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES, $charset));
 				$column++;
 			}
 		}
 
-		$worksheet->write($line,$column, get_lang('Title'));
+		$worksheet->SetCellValueByColumnAndRow($line,$column, get_lang('Title'));
 		$column++;
-		$worksheet->write($line,$column, get_lang('StartDate'));
+		$worksheet->SetCellValueByColumnAndRow($line,$column, get_lang('StartDate'));
         $column++;
-        $worksheet->write($line,$column, get_lang('EndDate'));
+        $worksheet->SetCellValueByColumnAndRow($line,$column, get_lang('EndDate'));
         $column++;
-        $worksheet->write($line,$column, get_lang('Duration').' ('.get_lang('MinMinutes').')');
+        $worksheet->SetCellValueByColumnAndRow($line,$column, get_lang('Duration').' ('.get_lang('MinMinutes').')');
 		$column++;
-		$worksheet->write($line,$column, get_lang('Score'));
+		$worksheet->SetCellValueByColumnAndRow($line,$column, get_lang('Score'));
 		$column++;
-		$worksheet->write($line,$column, get_lang('Total'));
+		$worksheet->SetCellValueByColumnAndRow($line,$column, get_lang('Total'));
 		$column++;
-        $worksheet->write($line,$column, get_lang('Status'));
+        $worksheet->SetCellValueByColumnAndRow($line,$column, get_lang('Status'));
 		$line++;
 
 		foreach ($this->results as $row) {
 			$column = 0;
 
             if ($with_column_user) {
-                $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['email']), ENT_QUOTES, $charset));
+                $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['email']), ENT_QUOTES, $charset));
                 $column++;
 
                 if (api_is_western_name_order()) {
-                    $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['first_name']), ENT_QUOTES, $charset));
+                    $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['first_name']), ENT_QUOTES, $charset));
                     $column++;
-                    $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['last_name']), ENT_QUOTES, $charset));
+                    $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['last_name']), ENT_QUOTES, $charset));
                     $column++;
                 } else {
-                    $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['last_name']), ENT_QUOTES, $charset));
+                    $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['last_name']), ENT_QUOTES, $charset));
                     $column++;
-                    $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['first_name']), ENT_QUOTES, $charset));
+                    $worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['first_name']), ENT_QUOTES, $charset));
                     $column++;
                 }
 			}
@@ -316,28 +315,32 @@ class HotpotatoesExerciseResult
 				//show user fields data, if any, for this user
 				$user_fields_values = UserManager::get_extra_user_data($row['user_id'],false,false, false, true);
 				foreach($user_fields_values as $value) {
-					$worksheet->write($line,$column, api_html_entity_decode(strip_tags($value), ENT_QUOTES, $charset));
+					$worksheet->SetCellValueByColumnAndRow($line,$column, api_html_entity_decode(strip_tags($value), ENT_QUOTES, $charset));
 					$column++;
 				}
 			}
 
-			$worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['title']), ENT_QUOTES, $charset));
+			$worksheet->SetCellValueByColumnAndRow($line,$column,api_html_entity_decode(strip_tags($row['title']), ENT_QUOTES, $charset));
 			$column++;
-			$worksheet->write($line,$column,$row['start_date']);
+			$worksheet->SetCellValueByColumnAndRow($line,$column,$row['start_date']);
             $column++;
-			$worksheet->write($line,$column,$row['end_date']);
+			$worksheet->SetCellValueByColumnAndRow($line,$column,$row['end_date']);
             $column++;
-			$worksheet->write($line,$column,$row['duration']);
+			$worksheet->SetCellValueByColumnAndRow($line,$column,$row['duration']);
 			$column++;
-			$worksheet->write($line,$column,$row['result']);
+			$worksheet->SetCellValueByColumnAndRow($line,$column,$row['result']);
 			$column++;
-			$worksheet->write($line,$column,$row['max']);
+			$worksheet->SetCellValueByColumnAndRow($line,$column,$row['max']);
 			$column++;
-            $worksheet->write($line,$column,$row['status']);
+            $worksheet->SetCellValueByColumnAndRow($line,$column,$row['status']);
 			$line++;
 		}
 
-		$workbook->close();
+        $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
+        $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
+        $writer->save($file);
+        DocumentManager::file_send_for_download($file, true, $filename);
+
 		return true;
 	}
 }

+ 10 - 8
main/exercice/savescores.php

@@ -51,15 +51,17 @@ function save_scores($file, $score)
         // anonymous
         $user_id = "NULL";
     }
-    $sql = "INSERT INTO $TABLETRACK_HOTPOTATOES (exe_name, exe_user_id, exe_date, c_id, exe_result, exe_weighting) VALUES (
-			'".Database::escape_string($file)."',
-			".intval($user_id).",
-			'".Database::escape_string($date)."',
-			$c_id,
-			'".Database::escape_string($score)."',
-			'".Database::escape_string($weighting)."')";
 
-    Database::query($sql);
+    $params = [
+        'exe_name' => $file,
+        'exe_user_id' => $user_id,
+        'exe_date' => $date,
+        'c_id' => $c_id,
+        'exe_result' => $score,
+        'exe_weighting' => $weighting,
+    ];
+    Database::insert($TABLETRACK_HOTPOTATOES, $params);
+
 
     if ($origin == 'learnpath') {
         //if we are in a learning path, save the score in the corresponding

+ 10 - 5
main/gradebook/lib/GradebookUtils.php

@@ -585,15 +585,20 @@ class GradebookUtils
      */
     public static function register_user_info_about_certificate($cat_id, $user_id, $score_certificate, $date_certificate)
     {
-        $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
-        $sql = 'SELECT COUNT(*) as count FROM ' . $table_certificate . ' gc
+        $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
+        $sql = 'SELECT COUNT(*) as count
+                FROM ' . $table . ' gc
                 WHERE gc.cat_id="' . intval($cat_id) . '" AND user_id="' . intval($user_id) . '" ';
         $rs_exist = Database::query($sql);
         $row = Database::fetch_array($rs_exist);
         if ($row['count'] == 0) {
-            $sql = 'INSERT INTO ' . $table_certificate . ' (cat_id,user_id,score_certificate,created_at)
-                    VALUES ("' . intval($cat_id) . '","' . intval($user_id) . '","' . Database::escape_string($score_certificate) . '","' . Database::escape_string($date_certificate) . '")';
-            Database::query($sql);
+            $params = [
+                'cat_id' => $cat_id,
+                'user_id' => $user_id,
+                'score_certificate' => $score_certificate,
+                'created_at' => $date_certificate
+            ];
+            Database::insert($table, $params);
         }
     }
 

+ 38 - 30
main/gradebook/lib/be/abstractlink.class.php

@@ -335,18 +335,17 @@ abstract class AbstractLink implements GradebookItem
             $row_testing = Database::fetch_array($result);
 
             if ($row_testing[0] == 0) {
-                $sql = 'INSERT INTO '.$tbl_grade_links.' (type, ref_id, user_id, course_code, category_id, weight, visible, created_at) VALUES ('
-                    .intval($this->get_type())
-                    .','.intval($this->get_ref_id())
-                    .','.intval($this->get_user_id())
-                    .",'".Database::escape_string($this->get_course_code())."'"
-                    .','.intval($this->get_category_id())
-                    .",'".Database::escape_string($this->get_weight())."'"
-                    .','.intval($this->is_visible());
-                $sql .= ','.'"'.$date_current = api_get_local_time().'"';
-                $sql .= ")";
-                Database::query($sql);
-                $inserted_id = Database::insert_id();
+                $params = [
+                    'type' => $this->get_type(),
+                    'ref_id' => $this->get_ref_id(),
+                    'user_id' => $this->get_user_id(),
+                    'course_code' => $this->get_course_code(),
+                    'category_id' => $this->get_category_id(),
+                    'weight' => $this->get_weight(),
+                    'visible' => $this->is_visible(),
+                    'created_at' => api_get_utc_datetime(),
+                ];
+                $inserted_id = Database::insert($tbl_grade_links, $params);
                 $this->set_id($inserted_id);
                 return $inserted_id;
             }
@@ -363,20 +362,21 @@ abstract class AbstractLink implements GradebookItem
     public function save()
     {
         $this->save_linked_data();
-        $tbl_grade_links = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
-        $sql = "UPDATE $tbl_grade_links SET
-                    type        = ".intval($this->get_type()).",
-                    ref_id      = ".intval($this->get_ref_id()).",
-                    user_id     = ".intval($this->get_user_id()).",
-                    course_code = '".Database::escape_string($this->get_course_code())."',
-                    category_id = ".intval($this->get_category_id()).",
-                    weight      = '".Database::escape_string($this->get_weight())."',
-                    visible     = ".intval($this->is_visible())."
-                 WHERE id = ".intval($this->id);
+        $table = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
+
+        $params = [
+            'type' => $this->get_type(),
+            'ref_id' => $this->get_ref_id(),
+            'user_id' => $this->get_user_id(),
+            'course_code' => $this->get_course_code(),
+            'category_id' => $this->get_category_id(),
+            'weight' => $this->get_weight(),
+            'visible' => $this->is_visible(),
+        ];
+        Database::insert($table, $params, ['id = ?' => $this->id]);
 
         AbstractLink::add_link_log($this->id);
 
-        Database::query($sql);
     }
 
     /**
@@ -384,14 +384,14 @@ abstract class AbstractLink implements GradebookItem
      */
     public static function add_link_log($idevaluation, $nameLog = null)
     {
-        $tbl_grade_linkeval_log = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_LINKEVAL_LOG);
-        $dateobject=AbstractLink::load ($idevaluation,null,null,null,null);
-        $current_date_server=api_get_utc_datetime();
+        $table = Database:: get_main_table(TABLE_MAIN_GRADEBOOK_LINKEVAL_LOG);
+        $dateobject = AbstractLink::load($idevaluation, null, null, null, null);
+        $current_date_server = api_get_utc_datetime();
         $arreval = get_object_vars($dateobject[0]);
         $description_log = isset($arreval['description']) ? $arreval['description']:'';
         if (empty($nameLog)) {
             if (isset($_POST['name_link'])) {
-                $name_log = isset($_POST['name_link']) ? Security::remove_XSS($_POST['name_link']) : $arreval['course_code'];
+                $name_log = isset($_POST['name_link']) ? $_POST['name_link'] : $arreval['course_code'];
             } elseif (isset($_POST['link_' . $idevaluation]) && $_POST['link_' . $idevaluation]) {
                 $name_log = $_POST['link_' . $idevaluation];
             } else {
@@ -400,10 +400,18 @@ abstract class AbstractLink implements GradebookItem
         } else {
             $name_log = $nameLog;
         }
-        $sql="INSERT INTO ".$tbl_grade_linkeval_log."(id_linkeval_log, name,description,created_at,weight,visible,type,user_id_log)
-              VALUES('".Database::escape_string($arreval['id'])."','".Database::escape_string($name_log)."','".Database::escape_string($description_log)."','".Database::escape_string($current_date_server)."','".Database::escape_string($arreval['weight'])."','".Database::escape_string($arreval['visible'])."','Link',".api_get_user_id().")";
 
-        Database::query($sql);
+        $params = [
+            'id_linkeval_log' => $arreval['id'],
+            'name' => $name_log,
+            'description' => $description_log,
+            'created_at' => $current_date_server,
+            'weight' => $arreval['weight'],
+            'visible' => $arreval['visible'],
+            'type' => 'Link',
+            'user_id_log' => api_get_user_id(),
+        ];
+        Database::insert($table, $params);
     }
 
     /**

+ 22 - 11
main/gradebook/lib/be/evaluation.class.php

@@ -352,7 +352,7 @@ class Evaluation implements GradebookItem
 	}
 
 	/**
-	 * @param $idevaluation
+	 * @param int $idevaluation
 	 */
 	public function add_evaluation_log($idevaluation)
 	{
@@ -363,13 +363,22 @@ class Evaluation implements GradebookItem
 			$dateobject = $eval->load($idevaluation,null,null,null,null);
 			$arreval = get_object_vars($dateobject[0]);
 			if (!empty($arreval['id'])) {
-				$sql_eval='SELECT weight from '.$tbl_grade_evaluations.' WHERE id='.$arreval['id'];
-				$rs=Database::query($sql_eval);
-				$row_old_weight=Database::fetch_array($rs,'ASSOC');
-				$current_date=api_get_utc_datetime();
-				$sql = "INSERT INTO ".$tbl_grade_linkeval_log."(id_linkeval_log,name,description,created_at,weight,visible,type,user_id_log)
-					  VALUES('".Database::escape_string($arreval['id'])."','".Database::escape_string($arreval['name'])."','".Database::escape_string($arreval['description'])."','".$current_date."','".Database::escape_string($row_old_weight['weight'])."','".Database::escape_string($arreval['visible'])."','evaluation',".api_get_user_id().")";
-				Database::query($sql);
+				$sql = 'SELECT weight from '.$tbl_grade_evaluations.'
+                        WHERE id='.$arreval['id'];
+                $rs = Database::query($sql);
+                $row_old_weight = Database::fetch_array($rs, 'ASSOC');
+                $current_date = api_get_utc_datetime();
+                $params = [
+                    'id_linkeval_log' => $arreval['id'],
+                    'name' => $arreval['name'],
+                    'description' => $arreval['description'],
+                    'created_at' => $current_date,
+                    'weight' => $row_old_weight['weight'],
+                    'visible' => $arreval['visible'],
+                    'type' => 'evaluation',
+                    'user_id_log' => api_get_user_id()
+                ];
+                Database::insert($tbl_grade_linkeval_log, $params);
 			}
 		}
 	}
@@ -478,8 +487,9 @@ class Evaluation implements GradebookItem
 	public function has_results()
 	{
 		$tbl_grade_results = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
-		$sql='SELECT count(id) AS number FROM '.$tbl_grade_results
-			.' WHERE evaluation_id = '.intval($this->id);
+		$sql = 'SELECT count(id) AS number
+				FROM '.$tbl_grade_results.'
+				WHERE evaluation_id = '.intval($this->id);
 		$result = Database::query($sql);
 		$number=Database::fetch_row($result);
 
@@ -492,7 +502,8 @@ class Evaluation implements GradebookItem
 	public function delete_results()
 	{
 		$tbl_grade_results = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
-		$sql = 'DELETE FROM '.$tbl_grade_results.' WHERE evaluation_id = '.intval($this->id);
+		$sql = 'DELETE FROM '.$tbl_grade_results.'
+				WHERE evaluation_id = '.intval($this->id);
 		Database::query($sql);
 	}
 

+ 13 - 13
main/gradebook/lib/gradebook_result.class.php

@@ -244,37 +244,37 @@ class GradeBookResult
      */
     public function exportCompleteReportXLS($data)
     {
-        $filename = 'gradebook-results-'.date('Y-m-d-h:i:s').'.xls';
-        include api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer.php';
-        $workbook = new Spreadsheet_Excel_Writer();
-        $workbook->setVersion(8); // BIFF8
-        $workbook->setTempDir(api_get_path(SYS_ARCHIVE_PATH));
-        $workbook->send($filename);
+        $filename = 'gradebook-results-'.api_get_local_time().'.xls';
 
-        $worksheet =& $workbook->addWorksheet('Report');
-        $worksheet->setInputEncoding(api_get_system_encoding());
+        $spreadsheet = new PHPExcel();
+        $spreadsheet->setActiveSheetIndex(0);
+        $worksheet = $spreadsheet->getActiveSheet();
 
         $line = 0;
         $column = 0; //skip the first column (row titles)
 
         //headers
         foreach ($data[0] as $header_col) {
-            $worksheet->write($line, $column, $header_col);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $header_col);
             $column++;
         }
         $line++;
 
         $cant_students = count($data[1]);
 
-        for ($i=0;$i<$cant_students;$i++) {
+        for ($i = 0; $i < $cant_students; $i++) {
             $column = 0;
             foreach ($data[1][$i] as $col_name) {
-                $worksheet->write($line,$column, html_entity_decode(strip_tags($col_name)));
+                $worksheet->SetCellValueByColumnAndRow($line,$column, html_entity_decode(strip_tags($col_name)));
                 $column++;
             }
             $line++;
         }
-        $workbook->close();
+
+        $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
+        $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
+        $writer->save($file);
+        DocumentManager::file_send_for_download($file, true, $filename);
         exit;
     }
 
@@ -284,7 +284,7 @@ class GradeBookResult
      */
     public function exportCompleteReportDOC($data)
     {
-        global $_course;
+        $_course = api_get_course_info();
         $filename = 'gb_results_'.$_course['code'].'_'.gmdate('YmdGis');
         $filepath = api_get_path(SYS_ARCHIVE_PATH).$filename;
         //build the results

+ 12 - 10
main/gradebook/lib/scoredisplay.class.php

@@ -195,10 +195,10 @@ class ScoreDisplay
      * @param int   score color percent (optional)
      * @param int   gradebook category id (optional)
      */
-    public function update_custom_score_display_settings ($displays, $scorecolpercent = 0, $category_id = null)
+    public function update_custom_score_display_settings($displays, $scorecolpercent = 0, $category_id = null)
     {
         $this->custom_display = $displays;
-           $this->custom_display_conv = $this->convert_displays($this->custom_display);
+        $this->custom_display_conv = $this->convert_displays($this->custom_display);
 
         if (isset($category_id)) {
             $category_id = intval($category_id);
@@ -207,21 +207,23 @@ class ScoreDisplay
         }
 
         // remove previous settings
-        $tbl_display = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
-        $sql = 'DELETE FROM '.$tbl_display.' WHERE category_id = '.$category_id;
+        $table = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
+        $sql = 'DELETE FROM '.$table.' WHERE category_id = '.$category_id;
         Database::query($sql);
 
         // add new settings
-        $sql = 'INSERT INTO '.$tbl_display.' (id, score, display, category_id, score_color_percent) VALUES ';
         $count = 0;
         foreach ($displays as $display) {
-            if ($count > 0) {
-                $sql .= ',';
-            }
-            $sql .= "(NULL, '".$display['score']."', '".Database::escape_string($display['display'])."', ".$category_id.", ".intval($scorecolpercent).")";
+            $params = [
+                'score' => $display['score'],
+                'display' => $display['display'],
+                'category_id' => $category_id,
+                'score_color_percent' => $scorecolpercent,
+            ];
+            Database::insert($table, $params);
+
             $count++;
         }
-        Database::query($sql);
     }
 
     /**

BIN
main/img/icons/64/plugins.png


+ 9 - 7
main/inc/global.inc.php

@@ -405,13 +405,15 @@ if (!empty($valid_languages)) {
     if (!in_array($user_language, $valid_languages['folder'])) {
         $user_language = api_get_setting('platformLanguage');
     }
+
     $language_priority1 = api_get_setting('languagePriority1');
     $language_priority2 = api_get_setting('languagePriority2');
     $language_priority3 = api_get_setting('languagePriority3');
     $language_priority4 = api_get_setting('languagePriority4');
 
-    if (in_array($user_language, $valid_languages['folder']) &&
-        (isset($_GET['language']) || isset($_POST['language_list']) || !empty($browser_language))
+    if (isset($_GET['language']) ||
+        (isset($_POST['language_list']) && !empty($_POST['language_list'])) ||
+        !empty($browser_language)
     ) {
         $user_selected_language = $user_language; // $_GET['language']; or HTTP_ACCEPT_LANGUAGE
         $_SESSION['user_language_choice'] = $user_selected_language;
@@ -419,13 +421,13 @@ if (!empty($valid_languages)) {
     }
 
     if (!empty($language_priority4) && api_get_language_from_type($language_priority4) !== false) {
-        $language_interface =  api_get_language_from_type($language_priority4);
+        $language_interface = api_get_language_from_type($language_priority4);
     } else {
         $language_interface = api_get_setting('platformLanguage');
     }
 
     if (!empty($language_priority3) && api_get_language_from_type($language_priority3) !== false) {
-        $language_interface =  api_get_language_from_type($language_priority3);
+        $language_interface = api_get_language_from_type($language_priority3);
     } else {
         if (isset($_SESSION['user_language_choice'])) {
             $language_interface = $_SESSION['user_language_choice'];
@@ -433,12 +435,13 @@ if (!empty($valid_languages)) {
     }
 
     if (!empty($language_priority2) && api_get_language_from_type($language_priority2) !== false) {
-        $language_interface =  api_get_language_from_type($language_priority2);
+        $language_interface = api_get_language_from_type($language_priority2);
     } else {
         if (isset($_user['language'])) {
             $language_interface = $_user['language'];
         }
     }
+
     if (!empty($language_priority1) && api_get_language_from_type($language_priority1) !== false) {
         $language_interface =  api_get_language_from_type($language_priority1);
     } else {
@@ -446,6 +449,7 @@ if (!empty($valid_languages)) {
             $language_interface = $_course['language'];
         }
     }
+
 }
 
 // Sometimes the variable $language_interface is changed
@@ -454,8 +458,6 @@ if (!empty($valid_languages)) {
 // to use it within the function get_lang(...).
 $language_interface_initial_value = $language_interface;
 
-
-
 /**
  * Include the trad4all language file
  */

+ 46 - 33
main/inc/lib/api.lib.php

@@ -1225,8 +1225,10 @@ function api_protect_teacher_script($allow_sessions_admins = false)
 
 /**
  * Function used to prevent anonymous users from accessing a script.
- *
+ * @param bool|true $printHeaders
  * @author Roan Embrechts
+ *
+ * @return bool
  */
 function api_block_anonymous_users($printHeaders = true)
 {
@@ -1279,9 +1281,10 @@ function api_get_navigator() {
 }
 
 /**
- * @return True if user selfregistration is allowed, false otherwise.
+ * @return True if user self registration is allowed, false otherwise.
  */
-function api_is_self_registration_allowed() {
+function api_is_self_registration_allowed()
+{
     return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
 }
 
@@ -1292,14 +1295,15 @@ function api_is_self_registration_allowed() {
  *          if (api_get_user_id())
  * @return integer the id of the current user, 0 if is empty
  */
-function api_get_user_id() {
+function api_get_user_id()
+{
     return empty($GLOBALS['_user']['user_id']) ? 0 : intval($GLOBALS['_user']['user_id']);
 }
 
 /**
  * Gets the list of courses a specific user is subscribed to
  * @param int       User ID
- * @param boolean   Whether to get session courses or not - NOT YET IMPLEMENTED
+ * @param boolean   $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
  * @return array    Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
  */
 function api_get_user_courses($userid, $fetch_session = true)
@@ -1338,6 +1342,8 @@ function api_get_user_courses($userid, $fetch_session = true)
  * This function should be only used inside api_get_user_info()
  *
  * @param array Non-standard user array
+ * @param bool $add_password
+ *
  * @return array Standard user array
  */
 function _api_format_user($user, $add_password = false)
@@ -1626,7 +1632,7 @@ function api_get_course_path($course_code = null)
 function api_get_course_setting($setting_name, $course_code = null)
 {
     $course_info = api_get_course_info($course_code);
-    $table       = Database::get_course_table(TABLE_COURSE_SETTING);
+    $table = Database::get_course_table(TABLE_COURSE_SETTING);
     $setting_name = Database::escape_string($setting_name);
     if (!empty($course_info['real_id']) && !empty($setting_name)) {
         $sql = "SELECT value FROM $table
@@ -1649,9 +1655,10 @@ function api_get_course_setting($setting_name, $course_code = null)
  * status of "6" (anonymous).
  * @return int  User ID of the anonymous user, or O if no anonymous user found
  */
-function api_get_anonymous_id() {
+function api_get_anonymous_id()
+{
     $table = Database::get_main_table(TABLE_MAIN_USER);
-    $sql = "SELECT user_id FROM $table WHERE status =".ANONYMOUS;
+    $sql = "SELECT user_id FROM $table WHERE status = ".ANONYMOUS;
     $res = Database::query($sql);
     if (Database::num_rows($res) > 0) {
         $row = Database::fetch_array($res);
@@ -2138,16 +2145,18 @@ class api_failure {
  * Gets the current Chamilo (not PHP/cookie) session ID
  * @return  int     O if no active session, the session ID otherwise
  */
-function api_get_session_id() {
-    return empty($_SESSION['id_session']) ? 0 : intval($_SESSION['id_session']);
+function api_get_session_id()
+{
+    return Session::read('id_session', 0);
 }
 
 /**
  * Gets the current Chamilo (not social network) group ID
  * @return  int     O if no active session, the session ID otherwise
  */
-function api_get_group_id() {
-    return empty($_SESSION['_gid']) ? 0 : intval($_SESSION['_gid']);
+function api_get_group_id()
+{
+    return Session::read('_gid', 0);
 }
 
 
@@ -2834,7 +2843,8 @@ function api_is_coach($session_id = 0, $courseId = null, $check_student_view = t
  * Checks whether the current user is a session administrator
  * @return boolean True if current user is a course administrator
  */
-function api_is_session_admin() {
+function api_is_session_admin()
+{
     $user = api_get_user_info();
     return isset($user['status']) && $user['status'] == SESSIONADMIN;
 }
@@ -2873,7 +2883,8 @@ function api_is_teacher()
  * Checks whether the current user is a invited user
  * @return boolean
  */
-function api_is_invitee() {
+function api_is_invitee()
+{
     $user = api_get_user_info();
 
     return isset($user['status']) && $user['status'] == INVITEE;
@@ -4241,37 +4252,39 @@ function api_get_language_id($language)
  * user_select_lang : language selected by user at login
  * course_lang : language of the current course
  * platform_lang : default platform language
- * @param string lang_type
- * @param return language of the requested type or false if the language is not available
+ * @param string $lang_type
+ * @return string
  **/
 function api_get_language_from_type($lang_type)
 {
-    global $_user;
-    global $_course;
-    $toreturn = false;
+    $_user = api_get_user_info();
+    $_course = api_get_course_info();
+    $return = false;
+
     switch ($lang_type) {
-        case 'platform_lang' :
+        case 'platform_lang':
             $temp_lang = api_get_setting('platformLanguage');
             if (!empty($temp_lang))
-                $toreturn = $temp_lang;
+                $return = $temp_lang;
             break;
-        case 'user_profil_lang' :
-            if (isset($_user['language']) && !empty($_user['language']) )
-                $toreturn = $_user['language'];
+        case 'user_profil_lang':
+            if (isset($_user['language']) && !empty($_user['language']))
+                $return = $_user['language'];
             break;
-        case 'user_selected_lang' :
-            if (isset($_SESSION['user_language_choice']) && !empty($_SESSION['user_language_choice']) )
-                $toreturn = ($_SESSION['user_language_choice']);
+        case 'user_selected_lang':
+            if (isset($_SESSION['user_language_choice']) && !empty($_SESSION['user_language_choice']))
+                $return = $_SESSION['user_language_choice'];
             break;
-        case 'course_lang' :
-            if (isset($_course['language']) && !empty($_course['language']) )
-                $toreturn = $_course['language'];
+        case 'course_lang':
+            if (isset($_course['language']) && !empty($_course['language']))
+                $return = $_course['language'];
             break;
-        default :
-            $toreturn = false;
+        default:
+            $return = false;
         break;
     }
-    return $toreturn;
+
+    return $return;
 }
 
 function api_get_language_info($language_id) {

+ 181 - 12
main/inc/lib/course.lib.php

@@ -3333,8 +3333,12 @@ class CourseManager
                         $course['status'] = STUDENT;
                     }
 
-                    $params['icon'] = Display::return_icon('blackboard.png', api_htmlentities($course_info['title']),
-                        array(), ICON_SIZE_LARGE);
+                    $params['icon'] = Display::return_icon(
+                        'blackboard.png',
+                        api_htmlentities($course_info['title']),
+                        array(),
+                        ICON_SIZE_LARGE
+                    );
 
                     $params['right_actions'] = '';
                     if (api_is_platform_admin()) {
@@ -3663,15 +3667,20 @@ class CourseManager
 
     /**
      * Retrieves the user defined course categories
-     * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
+     * @param string $userId
      * @return array containing all the titles of the user defined courses with the id as key of the array
      */
-    public static function get_user_course_categories()
+    public static function get_user_course_categories($userId = '')
     {
-        global $_user;
+        if ($userId == '') {
+            $realUserId = api_get_user_id();
+        } else {
+            $realUserId = $userId;
+        }
+
         $output = array();
         $table_category = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
-        $sql = "SELECT * FROM " . $table_category . " WHERE user_id='" . intval($_user['user_id']) . "'";
+        $sql = "SELECT * FROM $table_category WHERE user_id = '".intval($realUserId)."'";
         $result = Database::query($sql);
         while ($row = Database::fetch_array($result)) {
             $output[$row['id']] = $row['title'];
@@ -3679,6 +3688,37 @@ class CourseManager
         return $output;
     }
 
+    /**
+     * Return an array the user_category id and title for the course $courseId for user $userId
+     * @param $userId
+     * @param $courseId
+     * @return array
+     */
+    public static function getUserCourseCategoryForCourse($userId, $courseId)
+    {
+        $tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
+        $tblUserCategory = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
+        $courseId = intval($courseId);
+        $userId = intval($userId);
+
+        $sql = "SELECT user_course_cat, title
+                FROM $tblCourseRelUser cru
+                LEFT JOIN $tblUserCategory ucc
+                ON cru.user_course_cat = ucc.id
+                WHERE
+                    cru.user_id = $userId AND c_id= $courseId ";
+
+        $res = Database::query($sql);
+
+        $result = array();
+        if (Database::num_rows($res) > 0) {
+            $data = Database::fetch_assoc($res);
+            $result[] = $data['user_course_cat'];
+            $result[] = $data['title'];
+        }
+        return $result;
+    }
+
     /**
      * Get the course id based on the original id and field name in the extra fields.
      * Returns 0 if course was not found
@@ -4788,12 +4828,12 @@ class CourseManager
                             WHERE c_id = "' . $courseId . '" AND user_id = "' . $userId . '"  ';
                 } else {
                     $sql = "INSERT INTO " . $course_user_table . " SET
-                        c_id = '" . $courseId . "',
-                        user_id = '" . $userId . "',
-                        status = '1',
-                        is_tutor = '0',
-                        sort = '0',
-                        user_course_cat='0'";
+                            c_id = " . $courseId . ",
+                            user_id = " . $userId . ",
+                            status = '1',
+                            is_tutor = '0',
+                            sort = '0',
+                            user_course_cat='0'";
                 }
                 Database::query($sql);
             }
@@ -5510,4 +5550,133 @@ class CourseManager
 
         return $form_data;
     }
+
+    /**
+     * return html code for displaying a course title in the standard view (not the Session view)
+     * @param $courseId
+     * @param bool $loadDirs
+     * @return string
+     */
+    public static function displayCourseHtml($courseId, $loadDirs = false)
+    {
+        $params = self::getCourseParamsForDisplay($courseId, $loadDirs);
+        $html = self::course_item_html($params, false);
+        return $html;
+    }
+
+    /**
+     * Return tab of params to display a course title in the My Courses tab
+     * Check visibility, right, and notification icons, and load_dirs option
+     * @param $courseId
+     * @param bool $loadDirs
+     * @return array
+     */
+    public static function getCourseParamsForDisplay($courseId, $loadDirs = false)
+    {
+        $user_id = api_get_user_id();
+        // Table definitions
+        $TABLECOURS = Database :: get_main_table(TABLE_MAIN_COURSE);
+        $TABLECOURSUSER = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
+        $TABLE_ACCESS_URL_REL_COURSE = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
+        $current_url_id = api_get_current_access_url_id();
+
+        // Get course list auto-register
+        $special_course_list            = self::get_special_course_list();
+
+        $without_special_courses = '';
+        if (!empty($special_course_list)) {
+            $without_special_courses = ' AND course.code NOT IN ("'.implode('","',$special_course_list).'")';
+        }
+
+        //AND course_rel_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
+        $sql = "SELECT course.id, course.title, course.code, course.subscribe subscr, course.unsubscribe unsubscr, course_rel_user.status status,
+                course_rel_user.sort sort, course_rel_user.user_course_cat user_course_cat
+                FROM    $TABLECOURS      course,
+                        $TABLECOURSUSER  course_rel_user, ".$TABLE_ACCESS_URL_REL_COURSE." url
+                WHERE   course.id=".intval($courseId)."
+                        AND course.id = course_rel_user.c_id
+                        AND url.c_id = course.id
+                        AND course_rel_user.user_id = ".intval($user_id)."
+                        $without_special_courses ";
+
+        // If multiple URL access mode is enabled, only fetch courses
+        // corresponding to the current URL.
+        if (api_get_multiple_access_url() && $current_url_id != -1) {
+            $sql .= " AND url.course_code=course.code AND access_url_id=".intval($current_url_id);
+        }
+        // Use user's classification for courses (if any).
+        $sql .= " ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
+
+        $result = Database::query($sql);
+
+        // Browse through all courses. We can only have one course because of the  course.id=".intval($courseId) in sql query
+        $course = Database::fetch_array($result);
+        $course_info = api_get_course_info($course['code']);
+        //$course['id_session'] = null;
+        $course_info['id_session'] = null;
+        $course_info['status'] = $course['status'];
+
+        // For each course, get if there is any notification icon to show
+        // (something that would have changed since the user's last visit).
+        $show_notification = Display :: show_notification($course_info);
+
+        // New code displaying the user's status in respect to this course.
+        $status_icon = Display::return_icon('blackboard.png', $course_info['title'], array(), ICON_SIZE_LARGE);
+
+        $params = array();
+        $params['right_actions'] = '';
+
+        if (api_is_platform_admin()) {
+            if ($loadDirs) {
+                $params['right_actions'] .= '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview" href="javascript:void(0);">'.Display::return_icon('folder.png', get_lang('Documents'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
+                $params['right_actions'] .= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.Display::return_icon('edit.png', get_lang('Edit'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
+                $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
+            } else {
+                $params['right_actions'].= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.Display::return_icon('edit.png', get_lang('Edit'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
+            }
+
+            if ($course_info['status'] == COURSEMANAGER) {
+                //echo Display::return_icon('teachers.gif', get_lang('Status').': '.get_lang('Teacher'), array('style'=>'width: 11px; height: 11px;'));
+            }
+        } else {
+            if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
+                if ($loadDirs) {
+                    $params['right_actions'] .= '<a id="document_preview_'.$course_info['real_id'].'_0" class="document_preview" href="javascript:void(0);">'.Display::return_icon('folder.png', get_lang('Documents'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
+                    $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_0', 'class'=>'document_preview_container'));
+                } else {
+                    if ($course_info['status'] == COURSEMANAGER) {
+                        $params['right_actions'].= '<a href="'.api_get_path(WEB_CODE_PATH).'course_info/infocours.php?cidReq='.$course['code'].'">'.Display::return_icon('edit.png', get_lang('Edit'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
+                    }
+                }
+            }
+        }
+
+        $course_title_url = '';
+        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course['status'] == COURSEMANAGER) {
+            $course_title_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session=0';
+            $course_title = Display::url($course_info['title'], $course_title_url);
+        } else {
+            $course_title = $course_info['title']." ".Display::tag('span',get_lang('CourseClosed'), array('class'=>'item_closed'));
+        }
+
+        // Start displaying the course block itself
+        if (api_get_setting('display_coursecode_in_courselist') == 'true') {
+            $course_title .= ' ('.$course_info['visual_code'].') ';
+        }
+        $teachers = '';
+        if (api_get_setting('display_teacher_in_courselist') == 'true') {
+            $teachers = CourseManager::get_teacher_list_from_course_code_to_string($course['code'], self::USER_SEPARATOR, true);
+        }
+        $params['link'] = $course_title_url;
+        $params['icon'] = $status_icon;
+        $params['title'] = $course_title;
+        $params['teachers'] = $teachers;
+        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
+            $params['notifications'] = $show_notification;
+        }
+
+        return $params;
+    }
+
+
 }

+ 13 - 1
main/inc/lib/database.lib.php

@@ -321,7 +321,19 @@ class Database
      */
     public static function query($query)
     {
-        $result = self::getManager()->getConnection()->executeQuery($query);
+        $connection = self::getManager()->getConnection();
+
+        $result = false;
+
+        if (api_get_setting('server_type') == 'test') {
+            $result = $connection->executeQuery($query);
+        } else {
+            try {
+                $result = $connection->executeQuery($query);
+            } catch (Exception $e) {
+                api_not_allowed(true, get_lang('GeneralError'));
+            }
+        }
 
         return $result;
     }

+ 9 - 13
main/inc/lib/document.lib.php

@@ -1455,19 +1455,15 @@ class DocumentManager
     {
         // Database table definition
         $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
-
-        // creating the sql statement
-        $sql = "INSERT INTO $table_template
-                (title, description, course_code, user_id, ref_doc, image)
-                VALUES (
-                    '" . Database::escape_string($title) . "',
-                    '" . Database::escape_string($description) . "',
-                    '" . Database::escape_string($course_code) . "',
-                    '" . intval($user_id) . "',
-                    '" . Database::escape_string($document_id_for_template) . "',
-                    '" . Database::escape_string($image) . "')";
-        Database::query($sql);
-
+        $params = [
+            'title' => $title,
+            'description' => $description,
+            'course_code' => $course_code,
+            'user_id' => $user_id,
+            'ref_doc' => $document_id_for_template,
+            'image' => $image,
+        ];
+        Database::insert($table_template, $params);
         return true;
     }
 

+ 11 - 11
main/inc/lib/events.lib.php

@@ -34,19 +34,19 @@ class Event
         if ($pos === false && $referer != '') {
             $ip = api_get_real_ip();
             $remhost = @ getHostByAddr($ip);
-            if ($remhost == $ip)
-                $remhost = "Unknown"; // don't change this
+            if ($remhost == $ip) {
+                $remhost = "Unknown";
+            } // don't change this
             $reallyNow = api_get_utc_datetime();
-            $sql = "INSERT INTO ".$TABLETRACK_OPEN."
-        		(open_remote_host,
-        		 open_agent,
-        		 open_referer,
-        		 open_date)
-        		VALUES
-        		('".$remhost."',
-        		 '".Database::escape_string($_SERVER['HTTP_USER_AGENT'])."', '".Database::escape_string($referer)."', '$reallyNow')";
-            $res = Database::query($sql);
+            $params = [
+                'open_remote_host' => $remhost,
+                'open_agent' => $_SERVER['HTTP_USER_AGENT'],
+                'open_referer' => $referer,
+                'open_date' => $reallyNow,
+            ];
+            Database::insert($TABLETRACK_OPEN, $params);
         }
+
         return 1;
     }
 

+ 21 - 19
main/inc/lib/groupmanager.lib.php

@@ -816,29 +816,31 @@ class GroupManager
         if (!isset ($obj->new_order)) {
             $obj->new_order = 1;
         }
-        $sql = "INSERT INTO ".$table_group_category." SET
-                    c_id =  $course_id ,
-                    title='".Database::escape_string($title)."',
-                    display_order ='".$obj->new_order."',
-                    description='".Database::escape_string($description)."',
-                    doc_state = '".Database::escape_string($doc_state)."',
-                    work_state = '".Database::escape_string($work_state)."',
-                    calendar_state = '".Database::escape_string($calendar_state)."',
-                    announcements_state = '".Database::escape_string($announcements_state)."',
-                    forum_state = '".Database::escape_string($forum_state)."',
-                    wiki_state = '".Database::escape_string($wiki_state)."',
-                    chat_state = '".Database::escape_string($chat_state)."',
-                    groups_per_user   = '".Database::escape_string($groups_per_user)."',
-                    self_reg_allowed = '".Database::escape_string($self_registration_allowed)."',
-                    self_unreg_allowed = '".Database::escape_string($self_unregistration_allowed)."',
-                    max_student = '".Database::escape_string($maximum_number_of_students)."' ";
-        Database::query($sql);
-        $categoryId = Database::insert_id();
-        if ($categoryId) {
 
+        $params = [
+            'c_id' => $course_id,
+            'title' => $title,
+            'display_order' => $obj->new_order,
+            'description' => $description,
+            'doc_state' => $doc_state,
+            'work_state' => $work_state,
+            'calendar_state' => $calendar_state,
+            'announcements_state' => $announcements_state,
+            'forum_state' => $forum_state,
+            'wiki_state' => $wiki_state,
+            'chat_state' => $chat_state,
+            'groups_per_user' => $groups_per_user,
+            'self_reg_allowed' => $self_registration_allowed,
+            'self_unreg_allowed' => $self_unregistration_allowed,
+            'max_student' => $maximum_number_of_students
+        ];
+
+        $categoryId = Database::insert($table_group_category, $params);
+        if ($categoryId) {
             $sql = "UPDATE $table_group_category SET id = iid
                     WHERE iid = $categoryId";
             Database::query($sql);
+
             return $categoryId;
         }
 

+ 93 - 93
main/inc/lib/javascript/chat/js/chat.js

@@ -331,10 +331,10 @@ function chatWith(user_id, user_name, status) {
 }
 
 function chatNotYetWith(message) {
-    $("#message_ajax_reponse").html(message);
-    $("#message_ajax_reponse").css('display', 'block');
-    $("#message_ajax_reponse").attr('class', 'alert');
-    $('#message_ajax_reponse').alert()
+    $("#js_alerts").html(message);
+    $("#js_alerts").css('display', 'block');
+    $("#js_alerts").attr('class', 'alert alert-warning');
+    $('#js_alerts').alert()
 }
 
 /**
@@ -352,99 +352,99 @@ function createChatBox(user_id, chatboxtitle, minimizeChatBox, online) {
 
 	user_is_online = return_online_user(user_id, online);
 
-        var chatbox = $('<div>')
-            .attr({
-                id: 'chatbox_' + user_id
-            })
-            .addClass('chatbox')
-            .css('bottom', 0);
-
-        var chatboxHead = $('<div>')
-            .addClass('chatboxhead')
-            .append(user_is_online);
-
-        $('<div>')
-            .addClass('chatboxtitle')
-            .append(chatboxtitle)
-            .appendTo(chatboxHead);
-
-        var chatboxoptions = $('<div>')
-            .addClass('chatboxoptions')
-            .appendTo(chatboxHead);
-
-        if (!!Modernizr.prefixed('RTCPeerConnection', window)) {
-            $('<a>')
-                .addClass('btn btn-xs')
-                .attr({
-                    href: '#'
-                })
-                .html('<i class="fa fa-video-camera"></i>')
-                .on('click', function(e) {
-                    e.preventDefault();
-
-                    var createForm = $.get(
-                        ajax_url,
-                        {
-                            action: 'start_video',
-                            to: user_id
-                        }
-                    );
+	var chatbox = $('<div>')
+		.attr({
+			id: 'chatbox_' + user_id
+		})
+		.addClass('chatbox')
+		.css('bottom', 0);
+
+	var chatboxHead = $('<div>')
+		.addClass('chatboxhead')
+		.append(user_is_online);
+
+	$('<div>')
+		.addClass('chatboxtitle')
+		.append(chatboxtitle)
+		.appendTo(chatboxHead);
+
+	var chatboxoptions = $('<div>')
+		.addClass('chatboxoptions')
+		.appendTo(chatboxHead);
+
+	if (!!Modernizr.prefixed('RTCPeerConnection', window)) {
+		$('<a>')
+			.addClass('btn btn-xs')
+			.attr({
+				href: '#'
+			})
+			.html('<i class="fa fa-video-camera"></i>')
+			.on('click', function(e) {
+				e.preventDefault();
+
+				var createForm = $.get(
+					ajax_url,
+					{
+						action: 'start_video',
+						to: user_id
+					}
+				);
 
-                    $.when(createForm).done(function(response) {
-                        $('#global-modal')
-                            .find('.modal-dialog')
-                            .removeClass('modal-lg');
+				$.when(createForm).done(function(response) {
+					$('#global-modal')
+						.find('.modal-dialog')
+						.removeClass('modal-lg');
 
-                        $('#global-modal')
-                            .find('.modal-body')
-                            .html(response);
+					$('#global-modal')
+						.find('.modal-body')
+						.html(response);
 
-                        $('#global-modal').modal('show');
-                    });
-                })
-                .appendTo(chatboxoptions);
-        }
+					$('#global-modal').modal('show');
+				});
+			})
+			.appendTo(chatboxoptions);
+	}
 
-        $('<a>')
-            .addClass('btn btn-xs togglelink')
-            .attr({
-                href: 'javascript:void(0)',
-                rel: user_id
-            })
-            .html('<i class="fa fa-toggle-down"></i>')
-            .appendTo(chatboxoptions);
-
-        $('<a>')
-            .addClass('btn btn-xs closelink')
-            .attr({
-                href: 'javascript:void(0)',
-                rel: user_id
-            })
-            .html('<i class="fa fa-close"></i>')
-            .appendTo(chatboxoptions);
-
-        $('<br>')
-            .attr('clear', 'all')
-            .appendTo(chatboxHead);
-
-        var chatboxContent = $('<div>')
-            .addClass('chatboxcontent');
-
-        var chatboxInput = $('<div>')
-            .addClass('chatboxinput');
-
-        $('<textarea>')
-            .addClass('chatboxtextarea')
-            .on('keydown', function(e) {
-                return checkChatBoxInputKey(e.originalEvent, this, user_id);
-            })
-            .appendTo(chatboxInput);
-
-        chatbox
-            .append(chatboxHead)
-            .append(chatboxContent)
-            .append(chatboxInput)
-            .appendTo('body');
+	$('<a>')
+		.addClass('btn btn-xs togglelink')
+		.attr({
+			href: 'javascript:void(0)',
+			rel: user_id
+		})
+		.html('<i class="fa fa-toggle-down"></i>')
+		.appendTo(chatboxoptions);
+
+	$('<a>')
+		.addClass('btn btn-xs closelink')
+		.attr({
+			href: 'javascript:void(0)',
+			rel: user_id
+		})
+		.html('<i class="fa fa-close"></i>')
+		.appendTo(chatboxoptions);
+
+	$('<br>')
+		.attr('clear', 'all')
+		.appendTo(chatboxHead);
+
+	var chatboxContent = $('<div>')
+		.addClass('chatboxcontent');
+
+	var chatboxInput = $('<div>')
+		.addClass('chatboxinput');
+
+	$('<textarea>')
+		.addClass('chatboxtextarea')
+		.on('keydown', function(e) {
+			return checkChatBoxInputKey(e.originalEvent, this, user_id);
+		})
+		.appendTo(chatboxInput);
+
+	chatbox
+		.append(chatboxHead)
+		.append(chatboxContent)
+		.append(chatboxInput)
+		.appendTo('body');
 
 	chatBoxeslength = 0;
 

+ 35 - 15
main/inc/lib/message.lib.php

@@ -264,10 +264,19 @@ class MessageManager
                 Database::query($query);
                 $inbox_last_id = $edit_message_id;
             } else {
-                $query = "INSERT INTO $table_message (user_sender_id, user_receiver_id, msg_status, send_date, title, content, group_id, parent_id, update_date ) ".
-                         "VALUES ('$user_sender_id', '$receiver_user_id', '1', '".$now."','$clean_subject','$clean_content','$group_id','$parent_id', '".$now."')";
-                Database::query($query);
-                $inbox_last_id = Database::insert_id();
+
+                $params = [
+                    'user_sender_id' => $user_sender_id,
+                    'user_receiver_id' => $receiver_user_id,
+                    'msg_status' => '1',
+                    'send_date' => $now,
+                    'title' => $subject,
+                    'content' => $content,
+                    'group_id' => $group_id,
+                    'parent_id' => $parent_id,
+                    'update_date' => $now
+                ];
+                $inbox_last_id = Database::insert($table_message, $params);
             }
 
             // Save attachment file for inbox messages
@@ -289,11 +298,19 @@ class MessageManager
             }
 
             if (empty($group_id)) {
-                //message in outbox for user friend or group
-                $sql = "INSERT INTO $table_message (user_sender_id, user_receiver_id, msg_status, send_date, title, content, group_id, parent_id, update_date )
-                        VALUES ('$user_sender_id', '$receiver_user_id', '4', '".$now."','$clean_subject','$clean_content', '$group_id', '$parent_id', '".$now."')";
-                Database::query($sql);
-                $outbox_last_id = Database::insert_id();
+                // message in outbox for user friend or group
+                $params = [
+                    'user_sender_id' => $user_sender_id,
+                    'user_receiver_id' => $receiver_user_id,
+                    'msg_status' => '4',
+                    'send_date' => $now,
+                    'title' => $subject,
+                    'content' => $content,
+                    'group_id' => $group_id,
+                    'parent_id' => $parent_id,
+                    'update_date' => $now
+                ];
+                $outbox_last_id = Database::insert($table_message, $params);
 
                 // save attachment file for outbox messages
                 if (is_array($file_attachments)) {
@@ -574,13 +591,16 @@ class MessageManager
             if (is_uploaded_file($file_attach['tmp_name'])) {
                 @copy($file_attach['tmp_name'], $new_path);
             }
-            $safe_file_comment = Database::escape_string($file_comment);
-            $safe_file_name = Database::escape_string($file_name);
-            $safe_new_file_name = Database::escape_string($new_file_name);
+
             // Storing the attachments if any
-            $sql = "INSERT INTO $tbl_message_attach(filename,comment, path,message_id,size)
-				    VALUES ('$safe_file_name', '$safe_file_comment', '$safe_new_file_name' , '$message_id', '".$file_attach['size']."' )";
-            Database::query($sql);
+            $params = [
+                'filename' => $file_name,
+                'comment' => $file_comment,
+                'path' => $new_file_name,
+                'message_id' => $message_id,
+                'size' => $file_attach['size']
+            ];
+            Database::insert($tbl_message_attach, $params);
         }
     }
 

+ 1 - 1
main/inc/lib/online.inc.php

@@ -20,7 +20,7 @@
 use ChamiloSession as Session;
 
 function LoginCheck($uid) {
-	global $_course, $_configuration;
+	$_course = api_get_course_info();
 	$uid = (int) $uid;
 	$online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
     if (!empty($uid)) {

+ 0 - 104
main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer.php

@@ -1,104 +0,0 @@
-<?php
-/*
-*  Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
-*
-*  PERL Spreadsheet::WriteExcel module.
-*
-*  The author of the Spreadsheet::WriteExcel module is John McNamara
-*  <jmcnamara@cpan.org>
-*
-*  I _DO_ maintain this code, and John McNamara has nothing to do with the
-*  porting of this code to PHP.  Any questions directly related to this
-*  class library should be directed to me.
-*
-*  License Information:
-*
-*    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
-*    Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
-*
-*    This library is free software; you can redistribute it and/or
-*    modify it under the terms of the GNU Lesser General Public
-*    License as published by the Free Software Foundation; either
-*    version 2.1 of the License, or (at your option) any later version.
-*
-*    This library is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-*    Lesser General Public License for more details.
-*
-*    You should have received a copy of the GNU Lesser General Public
-*    License along with this library; if not, write to the Free Software
-*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-//require_once(api_get_path(LIBRARY_PATH).'pear/PEAR.php');
-require_once 'Writer/Workbook.php';
-
-/**
-* Class for writing Excel Spreadsheets. This class should change COMPLETELY.
-*
-* @author   Xavier Noguer <xnoguer@rezebra.com>
-* @category FileFormats
-* @package  Spreadsheet_Excel_Writer
-*/
-
-class Spreadsheet_Excel_Writer extends Spreadsheet_Excel_Writer_Workbook
-{
-    /**
-    * The constructor. It just creates a Workbook
-    *
-    * @param string $filename The optional filename for the Workbook.
-    * @return Spreadsheet_Excel_Writer_Workbook The Workbook created
-    */
-    function Spreadsheet_Excel_Writer($filename = '')
-    {
-        $this->_filename = $filename;
-        $this->Spreadsheet_Excel_Writer_Workbook($filename);
-    }
-
-    /**
-    * Send HTTP headers for the Excel file.
-    *
-    * @param string $filename The filename to use for HTTP headers
-    * @access public
-    */
-    function send($filename)
-    {
-        header("Content-type: application/vnd.ms-excel");
-        header("Content-Disposition: attachment; filename=\"$filename\"");
-        header("Expires: 0");
-        header("Cache-Control: must-revalidate, post-check=0,pre-check=0");
-        header("Pragma: public");
-    }
-
-    /**
-    * Utility function for writing formulas
-    * Converts a cell's coordinates to the A1 format.
-    *
-    * @access public
-    * @static
-    * @param integer $row Row for the cell to convert (0-indexed).
-    * @param integer $col Column for the cell to convert (0-indexed).
-    * @return string The cell identifier in A1 format
-    */
-    function rowcolToCell($row, $col)
-    {
-        if ($col > 255) { //maximum column value exceeded
-            return new PEAR_Error("Maximum column value exceeded: $col");
-        }
-
-        $int = (int)($col / 26);
-        $frac = $col % 26;
-        $chr1 = '';
-
-        if ($int > 0) {
-            $chr1 = chr(ord('A') + $int - 1);
-        }
-
-        $chr2 = chr(ord('A') + $frac);
-        $row++;
-
-        return $chr1 . $chr2 . $row;
-    }
-}
-?>

+ 0 - 261
main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/BIFFwriter.php

@@ -1,261 +0,0 @@
-<?php
-/*
-*  Module written/ported by Xavier Noguer <xnoguer@php.net>
-*
-*  The majority of this is _NOT_ my code.  I simply ported it from the
-*  PERL Spreadsheet::WriteExcel module.
-*
-*  The author of the Spreadsheet::WriteExcel module is John McNamara
-*  <jmcnamara@cpan.org>
-*
-*  I _DO_ maintain this code, and John McNamara has nothing to do with the
-*  porting of this code to PHP.  Any questions directly related to this
-*  class library should be directed to me.
-*
-*  License Information:
-*
-*    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
-*    Copyright (c) 2002-2003 Xavier Noguer xnoguer@php.net
-*
-*    This library is free software; you can redistribute it and/or
-*    modify it under the terms of the GNU Lesser General Public
-*    License as published by the Free Software Foundation; either
-*    version 2.1 of the License, or (at your option) any later version.
-*
-*    This library is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-*    Lesser General Public License for more details.
-*
-*    You should have received a copy of the GNU Lesser General Public
-*    License along with this library; if not, write to the Free Software
-*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-require_once 'PEAR.php';
-
-/**
-* Class for writing Excel BIFF records.
-*
-* From "MICROSOFT EXCEL BINARY FILE FORMAT" by Mark O'Brien (Microsoft Corporation):
-*
-* BIFF (BInary File Format) is the file format in which Excel documents are
-* saved on disk.  A BIFF file is a complete description of an Excel document.
-* BIFF files consist of sequences of variable-length records. There are many
-* different types of BIFF records.  For example, one record type describes a
-* formula entered into a cell; one describes the size and location of a
-* window into a document; another describes a picture format.
-*
-* @author   Xavier Noguer <xnoguer@php.net>
-* @category FileFormats
-* @package  Spreadsheet_Excel_Writer
-*/
-
-class Spreadsheet_Excel_Writer_BIFFwriter extends PEAR
-{
-    /**
-    * The BIFF/Excel version (5).
-    * @var integer
-    */
-    var $_BIFF_version = 0x0500;
-
-    /**
-    * The byte order of this architecture. 0 => little endian, 1 => big endian
-    * @var integer
-    */
-    var $_byte_order;
-
-    /**
-    * The string containing the data of the BIFF stream
-    * @var string
-    */
-    var $_data;
-
-    /**
-    * The size of the data in bytes. Should be the same as strlen($this->_data)
-    * @var integer
-    */
-    var $_datasize;
-
-    /**
-    * The maximun length for a BIFF record. See _addContinue()
-    * @var integer
-    * @see _addContinue()
-    */
-    var $_limit;
-
-    /**
-    * The temporary dir for storing the OLE file
-    * @var string
-    */
-    var $_tmp_dir;
-
-    /**
-    * Constructor
-    *
-    * @access public
-    */
-    function Spreadsheet_Excel_Writer_BIFFwriter()
-    {
-        $this->_byte_order = '';
-        $this->_data       = '';
-        $this->_datasize   = 0;
-        $this->_limit      = 2080;
-        $this->_tmp_dir    = '';
-        // Set the byte order
-        $this->_setByteOrder();
-    }
-
-    /**
-    * Determine the byte order and store it as class data to avoid
-    * recalculating it for each call to new().
-    *
-    * @access private
-    */
-    function _setByteOrder()
-    {
-        // Check if "pack" gives the required IEEE 64bit float
-        $teststr = pack("d", 1.2345);
-        $number  = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F);
-        if ($number == $teststr) {
-            $byte_order = 0;    // Little Endian
-        } elseif ($number == strrev($teststr)){
-            $byte_order = 1;    // Big Endian
-        } else {
-            // Give up. I'll fix this in a later version.
-            return $this->raiseError("Required floating point format ".
-                                     "not supported on this platform.");
-        }
-        $this->_byte_order = $byte_order;
-    }
-
-    /**
-    * General storage function
-    *
-    * @param string $data binary data to prepend
-    * @access private
-    */
-    function _prepend($data)
-    {
-        if (strlen($data) > $this->_limit) {
-            $data = $this->_addContinue($data);
-        }
-        $this->_data      = $data.$this->_data;
-        $this->_datasize += strlen($data);
-    }
-
-    /**
-    * General storage function
-    *
-    * @param string $data binary data to append
-    * @access private
-    */
-    function _append($data)
-    {
-        if (strlen($data) > $this->_limit) {
-            $data = $this->_addContinue($data);
-        }
-        $this->_data      = $this->_data.$data;
-        $this->_datasize += strlen($data);
-    }
-
-    /**
-    * Writes Excel BOF record to indicate the beginning of a stream or
-    * sub-stream in the BIFF file.
-    *
-    * @param  integer $type Type of BIFF file to write: 0x0005 Workbook,
-    *                       0x0010 Worksheet.
-    * @access private
-    */
-    function _storeBof($type)
-    {
-        $record  = 0x0809;        // Record identifier
-
-        // According to the SDK $build and $year should be set to zero.
-        // However, this throws a warning in Excel 5. So, use magic numbers.
-        if ($this->_BIFF_version == 0x0500) {
-            $length  = 0x0008;
-            $unknown = '';
-            $build   = 0x096C;
-            $year    = 0x07C9;
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $length  = 0x0010;
-            $unknown = pack("VV", 0x00000041, 0x00000006); //unknown last 8 bytes for BIFF8
-            $build   = 0x0DBB;
-            $year    = 0x07CC;
-        }
-        $version = $this->_BIFF_version;
-
-        $header  = pack("vv",   $record, $length);
-        $data    = pack("vvvv", $version, $type, $build, $year);
-        $this->_prepend($header . $data . $unknown);
-    }
-
-    /**
-    * Writes Excel EOF record to indicate the end of a BIFF stream.
-    *
-    * @access private
-    */
-    function _storeEof()
-    {
-        $record    = 0x000A;   // Record identifier
-        $length    = 0x0000;   // Number of bytes to follow
-        $header    = pack("vv", $record, $length);
-        $this->_append($header);
-    }
-
-    /**
-    * Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In
-    * Excel 97 the limit is 8228 bytes. Records that are longer than these limits
-    * must be split up into CONTINUE blocks.
-    *
-    * This function takes a long BIFF record and inserts CONTINUE records as
-    * necessary.
-    *
-    * @param  string  $data The original binary data to be written
-    * @return string        A very convenient string of continue blocks
-    * @access private
-    */
-    function _addContinue($data)
-    {
-        $limit  = $this->_limit;
-        $record = 0x003C;         // Record identifier
-
-        // The first 2080/8224 bytes remain intact. However, we have to change
-        // the length field of the record.
-        $tmp = substr($data, 0, 2).pack("v", $limit-4).substr($data, 4, $limit - 4);
-
-        $header = pack("vv", $record, $limit);  // Headers for continue records
-
-        // Retrieve chunks of 2080/8224 bytes +4 for the header.
-        $data_length = strlen($data);
-        for ($i = $limit; $i <  ($data_length - $limit); $i += $limit) {
-            $tmp .= $header;
-            $tmp .= substr($data, $i, $limit);
-        }
-
-        // Retrieve the last chunk of data
-        $header  = pack("vv", $record, strlen($data) - $i);
-        $tmp    .= $header;
-        $tmp    .= substr($data, $i, strlen($data) - $i);
-
-        return $tmp;
-    }
-
-    /**
-    * Sets the temp dir used for storing the OLE file
-    *
-    * @access public
-    * @param string $dir The dir to be used as temp dir
-    * @return true if given dir is valid, false otherwise
-    */
-    function setTempDir($dir)
-    {
-        if (is_dir($dir)) {
-            $this->_tmp_dir = $dir;
-            return true;
-        }
-        return false;
-    }
-}
-?>

+ 0 - 1114
main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Format.php

@@ -1,1114 +0,0 @@
-<?php
-/*
-*  Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
-*
-*  The majority of this is _NOT_ my code.  I simply ported it from the
-*  PERL Spreadsheet::WriteExcel module.
-*
-*  The author of the Spreadsheet::WriteExcel module is John McNamara
-*  <jmcnamara@cpan.org>
-*
-*  I _DO_ maintain this code, and John McNamara has nothing to do with the
-*  porting of this code to PHP.  Any questions directly related to this
-*  class library should be directed to me.
-*
-*  License Information:
-*
-*    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
-*    Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
-*
-*    This library is free software; you can redistribute it and/or
-*    modify it under the terms of the GNU Lesser General Public
-*    License as published by the Free Software Foundation; either
-*    version 2.1 of the License, or (at your option) any later version.
-*
-*    This library is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-*    Lesser General Public License for more details.
-*
-*    You should have received a copy of the GNU Lesser General Public
-*    License along with this library; if not, write to the Free Software
-*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-require_once 'PEAR.php';
-
-/**
-* Class for generating Excel XF records (formats)
-*
-* @author   Xavier Noguer <xnoguer@rezebra.com>
-* @category FileFormats
-* @package  Spreadsheet_Excel_Writer
-*/
-
-class Spreadsheet_Excel_Writer_Format extends PEAR
-{
-    /**
-    * The index given by the workbook when creating a new format.
-    * @var integer
-    */
-    var $_xf_index;
-
-    /**
-    * Index to the FONT record.
-    * @var integer
-    */
-    var $font_index;
-
-    /**
-    * The font name (ASCII).
-    * @var string
-    */
-    var $_font_name;
-
-    /**
-    * Height of font (1/20 of a point)
-    * @var integer
-    */
-    var $_size;
-
-    /**
-    * Bold style
-    * @var integer
-    */
-    var $_bold;
-
-    /**
-    * Bit specifiying if the font is italic.
-    * @var integer
-    */
-    var $_italic;
-
-    /**
-    * Index to the cell's color
-    * @var integer
-    */
-    var $_color;
-
-    /**
-    * The text underline property
-    * @var integer
-    */
-    var $_underline;
-
-    /**
-    * Bit specifiying if the font has strikeout.
-    * @var integer
-    */
-    var $_font_strikeout;
-
-    /**
-    * Bit specifiying if the font has outline.
-    * @var integer
-    */
-    var $_font_outline;
-
-    /**
-    * Bit specifiying if the font has shadow.
-    * @var integer
-    */
-    var $_font_shadow;
-
-    /**
-    * 2 bytes specifiying the script type for the font.
-    * @var integer
-    */
-    var $_font_script;
-
-    /**
-    * Byte specifiying the font family.
-    * @var integer
-    */
-    var $_font_family;
-
-    /**
-    * Byte specifiying the font charset.
-    * @var integer
-    */
-    var $_font_charset;
-
-    /**
-    * An index (2 bytes) to a FORMAT record (number format).
-    * @var integer
-    */
-    var $_num_format;
-
-    /**
-    * Bit specifying if formulas are hidden.
-    * @var integer
-    */
-    var $_hidden;
-
-    /**
-    * Bit specifying if the cell is locked.
-    * @var integer
-    */
-    var $_locked;
-
-    /**
-    * The three bits specifying the text horizontal alignment.
-    * @var integer
-    */
-    var $_text_h_align;
-
-    /**
-    * Bit specifying if the text is wrapped at the right border.
-    * @var integer
-    */
-    var $_text_wrap;
-
-    /**
-    * The three bits specifying the text vertical alignment.
-    * @var integer
-    */
-    var $_text_v_align;
-
-    /**
-    * 1 bit, apparently not used.
-    * @var integer
-    */
-    var $_text_justlast;
-
-    /**
-    * The two bits specifying the text rotation.
-    * @var integer
-    */
-    var $_rotation;
-
-    /**
-    * The cell's foreground color.
-    * @var integer
-    */
-    var $_fg_color;
-
-    /**
-    * The cell's background color.
-    * @var integer
-    */
-    var $_bg_color;
-
-    /**
-    * The cell's background fill pattern.
-    * @var integer
-    */
-    var $_pattern;
-
-    /**
-    * Style of the bottom border of the cell
-    * @var integer
-    */
-    var $_bottom;
-
-    /**
-    * Color of the bottom border of the cell.
-    * @var integer
-    */
-    var $_bottom_color;
-
-    /**
-    * Style of the top border of the cell
-    * @var integer
-    */
-    var $_top;
-
-    /**
-    * Color of the top border of the cell.
-    * @var integer
-    */
-    var $_top_color;
-
-    /**
-    * Style of the left border of the cell
-    * @var integer
-    */
-    var $_left;
-
-    /**
-    * Color of the left border of the cell.
-    * @var integer
-    */
-    var $_left_color;
-
-    /**
-    * Style of the right border of the cell
-    * @var integer
-    */
-    var $_right;
-
-    /**
-    * Color of the right border of the cell.
-    * @var integer
-    */
-    var $_right_color;
-
-    /**
-    * Constructor
-    *
-    * @access private
-    * @param integer $index the XF index for the format.
-    * @param array   $properties array with properties to be set on initialization.
-    */
-    function Spreadsheet_Excel_Writer_Format($BIFF_version, $index = 0, $properties =  array())
-    {
-        $this->_xf_index       = $index;
-        $this->_BIFF_version   = $BIFF_version;
-        $this->font_index      = 0;
-        $this->_font_name      = 'Arial';
-        $this->_size           = 10;
-        $this->_bold           = 0x0190;
-        $this->_italic         = 0;
-        $this->_color          = 0x7FFF;
-        $this->_underline      = 0;
-        $this->_font_strikeout = 0;
-        $this->_font_outline   = 0;
-        $this->_font_shadow    = 0;
-        $this->_font_script    = 0;
-        $this->_font_family    = 0;
-        $this->_font_charset   = 0;
-
-        $this->_num_format     = 0;
-
-        $this->_hidden         = 0;
-        $this->_locked         = 0;
-
-        $this->_text_h_align   = 0;
-        $this->_text_wrap      = 0;
-        $this->_text_v_align   = 2;
-        $this->_text_justlast  = 0;
-        $this->_rotation       = 0;
-
-        $this->_fg_color       = 0x40;
-        $this->_bg_color       = 0x41;
-
-        $this->_pattern        = 0;
-
-        $this->_bottom         = 0;
-        $this->_top            = 0;
-        $this->_left           = 0;
-        $this->_right          = 0;
-        $this->_diag           = 0;
-
-        $this->_bottom_color   = 0x40;
-        $this->_top_color      = 0x40;
-        $this->_left_color     = 0x40;
-        $this->_right_color    = 0x40;
-        $this->_diag_color     = 0x40;
-
-        // Set properties passed to Spreadsheet_Excel_Writer_Workbook::addFormat()
-        foreach ($properties as $property => $value)
-        {
-            if (method_exists($this, 'set'.ucwords($property))) {
-                $method_name = 'set'.ucwords($property);
-                $this->$method_name($value);
-            }
-        }
-    }
-
-
-    /**
-    * Generate an Excel BIFF XF record (style or cell).
-    *
-    * @param string $style The type of the XF record ('style' or 'cell').
-    * @return string The XF record
-    */
-    function getXf($style)
-    {
-        // Set the type of the XF record and some of the attributes.
-        if ($style == 'style') {
-            $style = 0xFFF5;
-        } else {
-            $style   = $this->_locked;
-            $style  |= $this->_hidden << 1;
-        }
-
-        // Flags to indicate if attributes have been set.
-        $atr_num     = ($this->_num_format != 0)?1:0;
-        $atr_fnt     = ($this->font_index != 0)?1:0;
-        $atr_alc     = ($this->_text_wrap)?1:0;
-        $atr_bdr     = ($this->_bottom   ||
-                        $this->_top      ||
-                        $this->_left     ||
-                        $this->_right)?1:0;
-        $atr_pat     = (($this->_fg_color != 0x40) ||
-                        ($this->_bg_color != 0x41) ||
-                        $this->_pattern)?1:0;
-        $atr_prot    = $this->_locked | $this->_hidden;
-
-        // Zero the default border colour if the border has not been set.
-        if ($this->_bottom == 0) {
-            $this->_bottom_color = 0;
-        }
-        if ($this->_top  == 0) {
-            $this->_top_color = 0;
-        }
-        if ($this->_right == 0) {
-            $this->_right_color = 0;
-        }
-        if ($this->_left == 0) {
-            $this->_left_color = 0;
-        }
-        if ($this->_diag == 0) {
-            $this->_diag_color = 0;
-        }
-
-        $record         = 0x00E0;              // Record identifier
-        if ($this->_BIFF_version == 0x0500) {
-            $length         = 0x0010;              // Number of bytes to follow
-        }
-        if ($this->_BIFF_version == 0x0600) {
-            $length         = 0x0014;
-        }
-
-        $ifnt           = $this->font_index;   // Index to FONT record
-        $ifmt           = $this->_num_format;  // Index to FORMAT record
-        if ($this->_BIFF_version == 0x0500) {
-            $align          = $this->_text_h_align;       // Alignment
-            $align         |= $this->_text_wrap     << 3;
-            $align         |= $this->_text_v_align  << 4;
-            $align         |= $this->_text_justlast << 7;
-            $align         |= $this->_rotation      << 8;
-            $align         |= $atr_num                << 10;
-            $align         |= $atr_fnt                << 11;
-            $align         |= $atr_alc                << 12;
-            $align         |= $atr_bdr                << 13;
-            $align         |= $atr_pat                << 14;
-            $align         |= $atr_prot               << 15;
-
-            $icv            = $this->_fg_color;       // fg and bg pattern colors
-            $icv           |= $this->_bg_color      << 7;
-
-            $fill           = $this->_pattern;        // Fill and border line style
-            $fill          |= $this->_bottom        << 6;
-            $fill          |= $this->_bottom_color  << 9;
-
-            $border1        = $this->_top;            // Border line style and color
-            $border1       |= $this->_left          << 3;
-            $border1       |= $this->_right         << 6;
-            $border1       |= $this->_top_color     << 9;
-
-            $border2        = $this->_left_color;     // Border color
-            $border2       |= $this->_right_color   << 7;
-
-            $header      = pack("vv",       $record, $length);
-            $data        = pack("vvvvvvvv", $ifnt, $ifmt, $style, $align,
-                                            $icv, $fill,
-                                            $border1, $border2);
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $align          = $this->_text_h_align;       // Alignment
-            $align         |= $this->_text_wrap     << 3;
-            $align         |= $this->_text_v_align  << 4;
-            $align         |= $this->_text_justlast << 7;
-
-            $used_attrib    = $atr_num              << 2;
-            $used_attrib   |= $atr_fnt              << 3;
-            $used_attrib   |= $atr_alc              << 4;
-            $used_attrib   |= $atr_bdr              << 5;
-            $used_attrib   |= $atr_pat              << 6;
-            $used_attrib   |= $atr_prot             << 7;
-
-            $icv            = $this->_fg_color;      // fg and bg pattern colors
-            $icv           |= $this->_bg_color      << 7;
-
-            $border1        = $this->_left;          // Border line style and color
-            $border1       |= $this->_right         << 4;
-            $border1       |= $this->_top           << 8;
-            $border1       |= $this->_bottom        << 12;
-            $border1       |= $this->_left_color    << 16;
-            $border1       |= $this->_right_color   << 23;
-            $diag_tl_to_rb = 0; // FIXME: add method
-            $diag_tr_to_lb = 0; // FIXME: add method
-            $border1       |= $diag_tl_to_rb        << 30;
-            $border1       |= $diag_tr_to_lb        << 31;
-
-            $border2        = $this->_top_color;    // Border color
-            $border2       |= $this->_bottom_color   << 7;
-            $border2       |= $this->_diag_color     << 14;
-            $border2       |= $this->_diag           << 21;
-            $border2       |= $this->_pattern        << 26;
-
-            $header      = pack("vv",       $record, $length);
-
-            $rotation      = $this->_rotation;
-            $biff8_options = 0x00;
-            $data  = pack("vvvC", $ifnt, $ifmt, $style, $align);
-            $data .= pack("CCC", $rotation, $biff8_options, $used_attrib);
-            $data .= pack("VVv", $border1, $border2, $icv);
-        }
-
-        return($header . $data);
-    }
-
-    /**
-    * Generate an Excel BIFF FONT record.
-    *
-    * @return string The FONT record
-    */
-    function getFont()
-    {
-        $dyHeight   = $this->_size * 20;    // Height of font (1/20 of a point)
-        $icv        = $this->_color;        // Index to color palette
-        $bls        = $this->_bold;         // Bold style
-        $sss        = $this->_font_script;  // Superscript/subscript
-        $uls        = $this->_underline;    // Underline
-        $bFamily    = $this->_font_family;  // Font family
-        $bCharSet   = $this->_font_charset; // Character set
-        $encoding   = 0;                    // TODO: Unicode support
-
-        $cch        = strlen($this->_font_name); // Length of font name
-        $record     = 0x31;                      // Record identifier
-        if ($this->_BIFF_version == 0x0500) {
-            $length     = 0x0F + $cch;            // Record length
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $length     = 0x10 + $cch;
-        }
-        $reserved   = 0x00;                // Reserved
-        $grbit      = 0x00;                // Font attributes
-        if ($this->_italic) {
-            $grbit     |= 0x02;
-        }
-        if ($this->_font_strikeout) {
-            $grbit     |= 0x08;
-        }
-        if ($this->_font_outline) {
-            $grbit     |= 0x10;
-        }
-        if ($this->_font_shadow) {
-            $grbit     |= 0x20;
-        }
-
-        $header  = pack("vv",         $record, $length);
-        if ($this->_BIFF_version == 0x0500) {
-            $data    = pack("vvvvvCCCCC", $dyHeight, $grbit, $icv, $bls,
-                                          $sss, $uls, $bFamily,
-                                          $bCharSet, $reserved, $cch);
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $data    = pack("vvvvvCCCCCC", $dyHeight, $grbit, $icv, $bls,
-                                           $sss, $uls, $bFamily,
-                                           $bCharSet, $reserved, $cch, $encoding);
-        }
-        return($header . $data . $this->_font_name);
-    }
-
-    /**
-    * Returns a unique hash key for a font.
-    * Used by Spreadsheet_Excel_Writer_Workbook::_storeAllFonts()
-    *
-    * The elements that form the key are arranged to increase the probability of
-    * generating a unique key. Elements that hold a large range of numbers
-    * (eg. _color) are placed between two binary elements such as _italic
-    *
-    * @return string A key for this font
-    */
-    function getFontKey()
-    {
-        $key  = "$this->_font_name$this->_size";
-        $key .= "$this->_font_script$this->_underline";
-        $key .= "$this->_font_strikeout$this->_bold$this->_font_outline";
-        $key .= "$this->_font_family$this->_font_charset";
-        $key .= "$this->_font_shadow$this->_color$this->_italic";
-        $key  = str_replace(' ', '_', $key);
-        return ($key);
-    }
-
-    /**
-    * Returns the index used by Spreadsheet_Excel_Writer_Worksheet::_XF()
-    *
-    * @return integer The index for the XF record
-    */
-    function getXfIndex()
-    {
-        return($this->_xf_index);
-    }
-
-    /**
-    * Used in conjunction with the set_xxx_color methods to convert a color
-    * string into a number. Color range is 0..63 but we will restrict it
-    * to 8..63 to comply with Gnumeric. Colors 0..7 are repeated in 8..15.
-    *
-    * @access private
-    * @param string $name_color name of the color (i.e.: 'blue', 'red', etc..). Optional.
-    * @return integer The color index
-    */
-    function _getColor($name_color = '')
-    {
-        $colors = array(
-                        'aqua'    => 0x0F,
-                        'cyan'    => 0x0F,
-                        'black'   => 0x08,
-                        'blue'    => 0x0C,
-                        'brown'   => 0x10,
-                        'magenta' => 0x0E,
-                        'fuchsia' => 0x0E,
-                        'gray'    => 0x17,
-                        'grey'    => 0x17,
-                        'green'   => 0x11,
-                        'lime'    => 0x0B,
-                        'navy'    => 0x12,
-                        'orange'  => 0x35,
-                        'purple'  => 0x14,
-                        'red'     => 0x0A,
-                        'silver'  => 0x16,
-                        'white'   => 0x09,
-                        'yellow'  => 0x0D
-                       );
-
-        // Return the default color, 0x7FFF, if undef,
-        if ($name_color == '') {
-            return(0x7FFF);
-        }
-
-        // or the color string converted to an integer,
-        if (isset($colors[$name_color])) {
-            return($colors[$name_color]);
-        }
-
-        // or the default color if string is unrecognised,
-        if (preg_match("/\D/",$name_color)) {
-            return(0x7FFF);
-        }
-
-        // or an index < 8 mapped into the correct range,
-        if ($name_color < 8) {
-            return($name_color + 8);
-        }
-
-        // or the default color if arg is outside range,
-        if ($name_color > 63) {
-            return(0x7FFF);
-        }
-
-        // or an integer in the valid range
-        return($name_color);
-    }
-
-    /**
-    * Set cell alignment.
-    *
-    * @access public
-    * @param string $location alignment for the cell ('left', 'right', etc...).
-    */
-    function setAlign($location)
-    {
-        if (preg_match("/\d/",$location)) {
-            return;                      // Ignore numbers
-        }
-
-        $location = strtolower($location);
-
-        if ($location == 'left') {
-            $this->_text_h_align = 1;
-        }
-        if ($location == 'centre') {
-            $this->_text_h_align = 2;
-        }
-        if ($location == 'center') {
-            $this->_text_h_align = 2;
-        }
-        if ($location == 'right') {
-            $this->_text_h_align = 3;
-        }
-        if ($location == 'fill') {
-            $this->_text_h_align = 4;
-        }
-        if ($location == 'justify') {
-            $this->_text_h_align = 5;
-        }
-        if ($location == 'merge') {
-            $this->_text_h_align = 6;
-        }
-        if ($location == 'equal_space') { // For T.K.
-            $this->_text_h_align = 7;
-        }
-        if ($location == 'top') {
-            $this->_text_v_align = 0;
-        }
-        if ($location == 'vcentre') {
-            $this->_text_v_align = 1;
-        }
-        if ($location == 'vcenter') {
-            $this->_text_v_align = 1;
-        }
-        if ($location == 'bottom') {
-            $this->_text_v_align = 2;
-        }
-        if ($location == 'vjustify') {
-            $this->_text_v_align = 3;
-        }
-        if ($location == 'vequal_space') { // For T.K.
-            $this->_text_v_align = 4;
-        }
-    }
-
-    /**
-    * Set cell horizontal alignment.
-    *
-    * @access public
-    * @param string $location alignment for the cell ('left', 'right', etc...).
-    */
-    function setHAlign($location)
-    {
-        if (preg_match("/\d/",$location)) {
-            return;                      // Ignore numbers
-        }
-
-        $location = strtolower($location);
-
-        if ($location == 'left') {
-            $this->_text_h_align = 1;
-        }
-        if ($location == 'centre') {
-            $this->_text_h_align = 2;
-        }
-        if ($location == 'center') {
-            $this->_text_h_align = 2;
-        }
-        if ($location == 'right') {
-            $this->_text_h_align = 3;
-        }
-        if ($location == 'fill') {
-            $this->_text_h_align = 4;
-        }
-        if ($location == 'justify') {
-            $this->_text_h_align = 5;
-        }
-        if ($location == 'merge') {
-            $this->_text_h_align = 6;
-        }
-        if ($location == 'equal_space') { // For T.K.
-            $this->_text_h_align = 7;
-        }
-    }
-
-    /**
-    * Set cell vertical alignment.
-    *
-    * @access public
-    * @param string $location alignment for the cell ('top', 'vleft', 'vright', etc...).
-    */
-    function setVAlign($location)
-    {
-        if (preg_match("/\d/",$location)) {
-            return;                      // Ignore numbers
-        }
-
-        $location = strtolower($location);
-
-        if ($location == 'top') {
-            $this->_text_v_align = 0;
-        }
-        if ($location == 'vcentre') {
-            $this->_text_v_align = 1;
-        }
-        if ($location == 'vcenter') {
-            $this->_text_v_align = 1;
-        }
-        if ($location == 'bottom') {
-            $this->_text_v_align = 2;
-        }
-        if ($location == 'vjustify') {
-            $this->_text_v_align = 3;
-        }
-        if ($location == 'vequal_space') { // For T.K.
-            $this->_text_v_align = 4;
-        }
-    }
-
-    /**
-    * This is an alias for the unintuitive setAlign('merge')
-    *
-    * @access public
-    */
-    function setMerge()
-    {
-        $this->setAlign('merge');
-    }
-
-    /**
-    * Sets the boldness of the text.
-    * Bold has a range 100..1000.
-    * 0 (400) is normal. 1 (700) is bold.
-    *
-    * @access public
-    * @param integer $weight Weight for the text, 0 maps to 400 (normal text),
-                             1 maps to 700 (bold text). Valid range is: 100-1000.
-                             It's Optional, default is 1 (bold).
-    */
-    function setBold($weight = 1)
-    {
-        if ($weight == 1) {
-            $weight = 0x2BC;  // Bold text
-        }
-        if ($weight == 0) {
-            $weight = 0x190;  // Normal text
-        }
-        if ($weight <  0x064) {
-            $weight = 0x190;  // Lower bound
-        }
-        if ($weight >  0x3E8) {
-            $weight = 0x190;  // Upper bound
-        }
-        $this->_bold = $weight;
-    }
-
-
-    /************************************
-    * FUNCTIONS FOR SETTING CELLS BORDERS
-    */
-
-    /**
-    * Sets the width for the bottom border of the cell
-    *
-    * @access public
-    * @param integer $style style of the cell border. 1 => thin, 2 => thick.
-    */
-    function setBottom($style)
-    {
-        $this->_bottom = $style;
-    }
-
-    /**
-    * Sets the width for the top border of the cell
-    *
-    * @access public
-    * @param integer $style style of the cell top border. 1 => thin, 2 => thick.
-    */
-    function setTop($style)
-    {
-        $this->_top = $style;
-    }
-
-    /**
-    * Sets the width for the left border of the cell
-    *
-    * @access public
-    * @param integer $style style of the cell left border. 1 => thin, 2 => thick.
-    */
-    function setLeft($style)
-    {
-        $this->_left = $style;
-    }
-
-    /**
-    * Sets the width for the right border of the cell
-    *
-    * @access public
-    * @param integer $style style of the cell right border. 1 => thin, 2 => thick.
-    */
-    function setRight($style)
-    {
-        $this->_right = $style;
-    }
-
-
-    /**
-    * Set cells borders to the same style
-    *
-    * @access public
-    * @param integer $style style to apply for all cell borders. 1 => thin, 2 => thick.
-    */
-    function setBorder($style)
-    {
-        $this->setBottom($style);
-        $this->setTop($style);
-        $this->setLeft($style);
-        $this->setRight($style);
-    }
-
-
-    /*******************************************
-    * FUNCTIONS FOR SETTING CELLS BORDERS COLORS
-    */
-
-    /**
-    * Sets all the cell's borders to the same color
-    *
-    * @access public
-    * @param mixed $color The color we are setting. Either a string (like 'blue'),
-    *                     or an integer (range is [8...63]).
-    */
-    function setBorderColor($color)
-    {
-        $this->setBottomColor($color);
-        $this->setTopColor($color);
-        $this->setLeftColor($color);
-        $this->setRightColor($color);
-    }
-
-    /**
-    * Sets the cell's bottom border color
-    *
-    * @access public
-    * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
-    */
-    function setBottomColor($color)
-    {
-        $value = $this->_getColor($color);
-        $this->_bottom_color = $value;
-    }
-
-    /**
-    * Sets the cell's top border color
-    *
-    * @access public
-    * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
-    */
-    function setTopColor($color)
-    {
-        $value = $this->_getColor($color);
-        $this->_top_color = $value;
-    }
-
-    /**
-    * Sets the cell's left border color
-    *
-    * @access public
-    * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
-    */
-    function setLeftColor($color)
-    {
-        $value = $this->_getColor($color);
-        $this->_left_color = $value;
-    }
-
-    /**
-    * Sets the cell's right border color
-    *
-    * @access public
-    * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
-    */
-    function setRightColor($color)
-    {
-        $value = $this->_getColor($color);
-        $this->_right_color = $value;
-    }
-
-
-    /**
-    * Sets the cell's foreground color
-    *
-    * @access public
-    * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
-    */
-    function setFgColor($color)
-    {
-        $value = $this->_getColor($color);
-        $this->_fg_color = $value;
-        if ($this->_pattern == 0) { // force color to be seen
-            $this->_pattern = 1;
-        }
-    }
-
-    /**
-    * Sets the cell's background color
-    *
-    * @access public
-    * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
-    */
-    function setBgColor($color)
-    {
-        $value = $this->_getColor($color);
-        $this->_bg_color = $value;
-        if ($this->_pattern == 0) { // force color to be seen
-            $this->_pattern = 1;
-        }
-    }
-
-    /**
-    * Sets the cell's color
-    *
-    * @access public
-    * @param mixed $color either a string (like 'blue'), or an integer (range is [8...63]).
-    */
-    function setColor($color)
-    {
-        $value = $this->_getColor($color);
-        $this->_color = $value;
-    }
-
-    /**
-    * Sets the fill pattern attribute of a cell
-    *
-    * @access public
-    * @param integer $arg Optional. Defaults to 1. Meaningful values are: 0-18,
-    *                     0 meaning no background.
-    */
-    function setPattern($arg = 1)
-    {
-        $this->_pattern = $arg;
-    }
-
-    /**
-    * Sets the underline of the text
-    *
-    * @access public
-    * @param integer $underline The value for underline. Possible values are:
-    *                          1 => underline, 2 => double underline.
-    */
-    function setUnderline($underline)
-    {
-        $this->_underline = $underline;
-    }
-
-    /**
-    * Sets the font style as italic
-    *
-    * @access public
-    */
-    function setItalic()
-    {
-        $this->_italic = 1;
-    }
-
-    /**
-    * Sets the font size
-    *
-    * @access public
-    * @param integer $size The font size (in pixels I think).
-    */
-    function setSize($size)
-    {
-        $this->_size = $size;
-    }
-
-    /**
-    * Sets text wrapping
-    *
-    * @access public
-    */
-    function setTextWrap()
-    {
-        $this->_text_wrap = 1;
-    }
-
-    /**
-    * Sets the orientation of the text
-    *
-    * @access public
-    * @param integer $angle The rotation angle for the text (clockwise). Possible
-                            values are: 0, 90, 270 and -1 for stacking top-to-bottom.
-    */
-    function setTextRotation($angle)
-    {
-        switch ($angle)
-        {
-            case 0:
-                $this->_rotation = 0;
-                break;
-            case 90:
-                if ($this->_BIFF_version == 0x0500) {
-                $this->_rotation = 3;
-                } elseif ($this->_BIFF_version == 0x0600) {
-                    $this->_rotation = 180;
-                }
-                break;
-            case 270:
-                if ($this->_BIFF_version == 0x0500) {
-                $this->_rotation = 2;
-                } elseif ($this->_BIFF_version == 0x0600) {
-                    $this->_rotation = 90;
-                }
-                break;
-            case -1:
-                if ($this->_BIFF_version == 0x0500) {
-                $this->_rotation = 1;
-                } elseif ($this->_BIFF_version == 0x0600) {
-                    $this->_rotation = 255;
-                }
-                break;
-            default :
-                return $this->raiseError("Invalid value for angle.".
-                                  " Possible values are: 0, 90, 270 and -1 ".
-                                  "for stacking top-to-bottom.");
-                $this->_rotation = 0;
-                break;
-        }
-    }
-
-    /**
-    * Sets the numeric format.
-    * It can be date, time, currency, etc...
-    *
-    * @access public
-    * @param integer $num_format The numeric format.
-    */
-    function setNumFormat($num_format)
-    {
-        $this->_num_format = $num_format;
-    }
-
-    /**
-    * Sets font as strikeout.
-    *
-    * @access public
-    */
-    function setStrikeOut()
-    {
-        $this->_font_strikeout = 1;
-    }
-
-    /**
-    * Sets outlining for a font.
-    *
-    * @access public
-    */
-    function setOutLine()
-    {
-        $this->_font_outline = 1;
-    }
-
-    /**
-    * Sets font as shadow.
-    *
-    * @access public
-    */
-    function setShadow()
-    {
-        $this->_font_shadow = 1;
-    }
-
-    /**
-    * Sets the script type of the text
-    *
-    * @access public
-    * @param integer $script The value for script type. Possible values are:
-    *                        1 => superscript, 2 => subscript.
-    */
-    function setScript($script)
-    {
-        $this->_font_script = $script;
-    }
-
-     /**
-     * Locks a cell.
-     *
-     * @access public
-     */
-     function setLocked()
-     {
-         $this->_locked = 1;
-     }
-
-    /**
-    * Unlocks a cell. Useful for unprotecting particular cells of a protected sheet.
-    *
-    * @access public
-    */
-    function setUnLocked()
-    {
-        $this->_locked = 0;
-    }
-
-    /**
-    * Sets the font family name.
-    *
-    * @access public
-    * @param string $fontfamily The font family name. Possible values are:
-    *                           'Times New Roman', 'Arial', 'Courier'.
-    */
-    function setFontFamily($font_family)
-    {
-        $this->_font_name = $font_family;
-    }
-}
-?>

+ 0 - 1703
main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Parser.php

@@ -1,1703 +0,0 @@
-<?php
-/**
-*  Class for parsing Excel formulas
-*
-*  License Information:
-*
-*    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
-*    Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
-*
-*    This library is free software; you can redistribute it and/or
-*    modify it under the terms of the GNU Lesser General Public
-*    License as published by the Free Software Foundation; either
-*    version 2.1 of the License, or (at your option) any later version.
-*
-*    This library is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-*    Lesser General Public License for more details.
-*
-*    You should have received a copy of the GNU Lesser General Public
-*    License along with this library; if not, write to the Free Software
-*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_ADD token identifier for character "+"
-*/
-define('SPREADSHEET_EXCEL_WRITER_ADD', "+");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_SUB token identifier for character "-"
-*/
-define('SPREADSHEET_EXCEL_WRITER_SUB', "-");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_MUL token identifier for character "*"
-*/
-define('SPREADSHEET_EXCEL_WRITER_MUL', "*");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_DIV token identifier for character "/"
-*/
-define('SPREADSHEET_EXCEL_WRITER_DIV', "/");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_OPEN token identifier for character "("
-*/
-define('SPREADSHEET_EXCEL_WRITER_OPEN', "(");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_CLOSE token identifier for character ")"
-*/
-define('SPREADSHEET_EXCEL_WRITER_CLOSE', ")");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_COMA token identifier for character ","
-*/
-define('SPREADSHEET_EXCEL_WRITER_COMA', ",");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_SEMICOLON token identifier for character ";"
-*/
-define('SPREADSHEET_EXCEL_WRITER_SEMICOLON', ";");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_GT token identifier for character ">"
-*/
-define('SPREADSHEET_EXCEL_WRITER_GT', ">");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_LT token identifier for character "<"
-*/
-define('SPREADSHEET_EXCEL_WRITER_LT', "<");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_LE token identifier for character "<="
-*/
-define('SPREADSHEET_EXCEL_WRITER_LE', "<=");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_GE token identifier for character ">="
-*/
-define('SPREADSHEET_EXCEL_WRITER_GE', ">=");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_EQ token identifier for character "="
-*/
-define('SPREADSHEET_EXCEL_WRITER_EQ', "=");
-
-/**
-* @const SPREADSHEET_EXCEL_WRITER_NE token identifier for character "<>"
-*/
-define('SPREADSHEET_EXCEL_WRITER_NE', "<>");
-
-/**
-* * @const SPREADSHEET_EXCEL_WRITER_CONCAT token identifier for character "&"
-*/
-define('SPREADSHEET_EXCEL_WRITER_CONCAT', "&");
-
-require_once 'PEAR.php';
-
-/**
-* Class for parsing Excel formulas
-*
-* @author   Xavier Noguer <xnoguer@rezebra.com>
-* @category FileFormats
-* @package  Spreadsheet_Excel_Writer
-*/
-
-class Spreadsheet_Excel_Writer_Parser extends PEAR
-{
-    /**
-    * The index of the character we are currently looking at
-    * @var integer
-    */
-    var $_current_char;
-
-    /**
-    * The token we are working on.
-    * @var string
-    */
-    var $_current_token;
-
-    /**
-    * The formula to parse
-    * @var string
-    */
-    var $_formula;
-
-    /**
-    * The character ahead of the current char
-    * @var string
-    */
-    var $_lookahead;
-
-    /**
-    * The parse tree to be generated
-    * @var string
-    */
-    var $_parse_tree;
-
-    /**
-    * The byte order. 1 => big endian, 0 => little endian.
-    * @var integer
-    */
-    var $_byte_order;
-
-    /**
-    * Array of external sheets
-    * @var array
-    */
-    var $_ext_sheets;
-
-    /**
-    * Array of sheet references in the form of REF structures
-    * @var array
-    */
-    var $_references;
-
-    /**
-    * The BIFF version for the workbook
-    * @var integer
-    */
-    var $_BIFF_version;
-
-    /**
-    * The class constructor
-    *
-    * @param integer $byte_order The byte order (Little endian or Big endian) of the architecture
-                                 (optional). 1 => big endian, 0 (default) little endian.
-    */
-    function Spreadsheet_Excel_Writer_Parser($byte_order, $biff_version)
-    {
-        $this->_current_char  = 0;
-        $this->_BIFF_version  = $biff_version;
-        $this->_current_token = '';       // The token we are working on.
-        $this->_formula       = '';       // The formula to parse.
-        $this->_lookahead     = '';       // The character ahead of the current char.
-        $this->_parse_tree    = '';       // The parse tree to be generated.
-        $this->_initializeHashes();      // Initialize the hashes: ptg's and function's ptg's
-        $this->_byte_order = $byte_order; // Little Endian or Big Endian
-        $this->_ext_sheets = array();
-        $this->_references = array();
-    }
-
-    /**
-    * Initialize the ptg and function hashes.
-    *
-    * @access private
-    */
-    function _initializeHashes()
-    {
-        // The Excel ptg indices
-        $this->ptg = array(
-            'ptgExp'       => 0x01,
-            'ptgTbl'       => 0x02,
-            'ptgAdd'       => 0x03,
-            'ptgSub'       => 0x04,
-            'ptgMul'       => 0x05,
-            'ptgDiv'       => 0x06,
-            'ptgPower'     => 0x07,
-            'ptgConcat'    => 0x08,
-            'ptgLT'        => 0x09,
-            'ptgLE'        => 0x0A,
-            'ptgEQ'        => 0x0B,
-            'ptgGE'        => 0x0C,
-            'ptgGT'        => 0x0D,
-            'ptgNE'        => 0x0E,
-            'ptgIsect'     => 0x0F,
-            'ptgUnion'     => 0x10,
-            'ptgRange'     => 0x11,
-            'ptgUplus'     => 0x12,
-            'ptgUminus'    => 0x13,
-            'ptgPercent'   => 0x14,
-            'ptgParen'     => 0x15,
-            'ptgMissArg'   => 0x16,
-            'ptgStr'       => 0x17,
-            'ptgAttr'      => 0x19,
-            'ptgSheet'     => 0x1A,
-            'ptgEndSheet'  => 0x1B,
-            'ptgErr'       => 0x1C,
-            'ptgBool'      => 0x1D,
-            'ptgInt'       => 0x1E,
-            'ptgNum'       => 0x1F,
-            'ptgArray'     => 0x20,
-            'ptgFunc'      => 0x21,
-            'ptgFuncVar'   => 0x22,
-            'ptgName'      => 0x23,
-            'ptgRef'       => 0x24,
-            'ptgArea'      => 0x25,
-            'ptgMemArea'   => 0x26,
-            'ptgMemErr'    => 0x27,
-            'ptgMemNoMem'  => 0x28,
-            'ptgMemFunc'   => 0x29,
-            'ptgRefErr'    => 0x2A,
-            'ptgAreaErr'   => 0x2B,
-            'ptgRefN'      => 0x2C,
-            'ptgAreaN'     => 0x2D,
-            'ptgMemAreaN'  => 0x2E,
-            'ptgMemNoMemN' => 0x2F,
-            'ptgNameX'     => 0x39,
-            'ptgRef3d'     => 0x3A,
-            'ptgArea3d'    => 0x3B,
-            'ptgRefErr3d'  => 0x3C,
-            'ptgAreaErr3d' => 0x3D,
-            'ptgArrayV'    => 0x40,
-            'ptgFuncV'     => 0x41,
-            'ptgFuncVarV'  => 0x42,
-            'ptgNameV'     => 0x43,
-            'ptgRefV'      => 0x44,
-            'ptgAreaV'     => 0x45,
-            'ptgMemAreaV'  => 0x46,
-            'ptgMemErrV'   => 0x47,
-            'ptgMemNoMemV' => 0x48,
-            'ptgMemFuncV'  => 0x49,
-            'ptgRefErrV'   => 0x4A,
-            'ptgAreaErrV'  => 0x4B,
-            'ptgRefNV'     => 0x4C,
-            'ptgAreaNV'    => 0x4D,
-            'ptgMemAreaNV' => 0x4E,
-            'ptgMemNoMemN' => 0x4F,
-            'ptgFuncCEV'   => 0x58,
-            'ptgNameXV'    => 0x59,
-            'ptgRef3dV'    => 0x5A,
-            'ptgArea3dV'   => 0x5B,
-            'ptgRefErr3dV' => 0x5C,
-            'ptgAreaErr3d' => 0x5D,
-            'ptgArrayA'    => 0x60,
-            'ptgFuncA'     => 0x61,
-            'ptgFuncVarA'  => 0x62,
-            'ptgNameA'     => 0x63,
-            'ptgRefA'      => 0x64,
-            'ptgAreaA'     => 0x65,
-            'ptgMemAreaA'  => 0x66,
-            'ptgMemErrA'   => 0x67,
-            'ptgMemNoMemA' => 0x68,
-            'ptgMemFuncA'  => 0x69,
-            'ptgRefErrA'   => 0x6A,
-            'ptgAreaErrA'  => 0x6B,
-            'ptgRefNA'     => 0x6C,
-            'ptgAreaNA'    => 0x6D,
-            'ptgMemAreaNA' => 0x6E,
-            'ptgMemNoMemN' => 0x6F,
-            'ptgFuncCEA'   => 0x78,
-            'ptgNameXA'    => 0x79,
-            'ptgRef3dA'    => 0x7A,
-            'ptgArea3dA'   => 0x7B,
-            'ptgRefErr3dA' => 0x7C,
-            'ptgAreaErr3d' => 0x7D
-            );
-
-        // Thanks to Michael Meeks and Gnumeric for the initial arg values.
-        //
-        // The following hash was generated by "function_locale.pl" in the distro.
-        // Refer to function_locale.pl for non-English function names.
-        //
-        // The array elements are as follow:
-        // ptg:   The Excel function ptg code.
-        // args:  The number of arguments that the function takes:
-        //           >=0 is a fixed number of arguments.
-        //           -1  is a variable  number of arguments.
-        // class: The reference, value or array class of the function args.
-        // vol:   The function is volatile.
-        //
-        $this->_functions = array(
-              // function                  ptg  args  class  vol
-              'COUNT'           => array(   0,   -1,    0,    0 ),
-              'IF'              => array(   1,   -1,    1,    0 ),
-              'ISNA'            => array(   2,    1,    1,    0 ),
-              'ISERROR'         => array(   3,    1,    1,    0 ),
-              'SUM'             => array(   4,   -1,    0,    0 ),
-              'AVERAGE'         => array(   5,   -1,    0,    0 ),
-              'MIN'             => array(   6,   -1,    0,    0 ),
-              'MAX'             => array(   7,   -1,    0,    0 ),
-              'ROW'             => array(   8,   -1,    0,    0 ),
-              'COLUMN'          => array(   9,   -1,    0,    0 ),
-              'NA'              => array(  10,    0,    0,    0 ),
-              'NPV'             => array(  11,   -1,    1,    0 ),
-              'STDEV'           => array(  12,   -1,    0,    0 ),
-              'DOLLAR'          => array(  13,   -1,    1,    0 ),
-              'FIXED'           => array(  14,   -1,    1,    0 ),
-              'SIN'             => array(  15,    1,    1,    0 ),
-              'COS'             => array(  16,    1,    1,    0 ),
-              'TAN'             => array(  17,    1,    1,    0 ),
-              'ATAN'            => array(  18,    1,    1,    0 ),
-              'PI'              => array(  19,    0,    1,    0 ),
-              'SQRT'            => array(  20,    1,    1,    0 ),
-              'EXP'             => array(  21,    1,    1,    0 ),
-              'LN'              => array(  22,    1,    1,    0 ),
-              'LOG10'           => array(  23,    1,    1,    0 ),
-              'ABS'             => array(  24,    1,    1,    0 ),
-              'INT'             => array(  25,    1,    1,    0 ),
-              'SIGN'            => array(  26,    1,    1,    0 ),
-              'ROUND'           => array(  27,    2,    1,    0 ),
-              'LOOKUP'          => array(  28,   -1,    0,    0 ),
-              'INDEX'           => array(  29,   -1,    0,    1 ),
-              'REPT'            => array(  30,    2,    1,    0 ),
-              'MID'             => array(  31,    3,    1,    0 ),
-              'LEN'             => array(  32,    1,    1,    0 ),
-              'VALUE'           => array(  33,    1,    1,    0 ),
-              'TRUE'            => array(  34,    0,    1,    0 ),
-              'FALSE'           => array(  35,    0,    1,    0 ),
-              'AND'             => array(  36,   -1,    0,    0 ),
-              'OR'              => array(  37,   -1,    0,    0 ),
-              'NOT'             => array(  38,    1,    1,    0 ),
-              'MOD'             => array(  39,    2,    1,    0 ),
-              'DCOUNT'          => array(  40,    3,    0,    0 ),
-              'DSUM'            => array(  41,    3,    0,    0 ),
-              'DAVERAGE'        => array(  42,    3,    0,    0 ),
-              'DMIN'            => array(  43,    3,    0,    0 ),
-              'DMAX'            => array(  44,    3,    0,    0 ),
-              'DSTDEV'          => array(  45,    3,    0,    0 ),
-              'VAR'             => array(  46,   -1,    0,    0 ),
-              'DVAR'            => array(  47,    3,    0,    0 ),
-              'TEXT'            => array(  48,    2,    1,    0 ),
-              'LINEST'          => array(  49,   -1,    0,    0 ),
-              'TREND'           => array(  50,   -1,    0,    0 ),
-              'LOGEST'          => array(  51,   -1,    0,    0 ),
-              'GROWTH'          => array(  52,   -1,    0,    0 ),
-              'PV'              => array(  56,   -1,    1,    0 ),
-              'FV'              => array(  57,   -1,    1,    0 ),
-              'NPER'            => array(  58,   -1,    1,    0 ),
-              'PMT'             => array(  59,   -1,    1,    0 ),
-              'RATE'            => array(  60,   -1,    1,    0 ),
-              'MIRR'            => array(  61,    3,    0,    0 ),
-              'IRR'             => array(  62,   -1,    0,    0 ),
-              'RAND'            => array(  63,    0,    1,    1 ),
-              'MATCH'           => array(  64,   -1,    0,    0 ),
-              'DATE'            => array(  65,    3,    1,    0 ),
-              'TIME'            => array(  66,    3,    1,    0 ),
-              'DAY'             => array(  67,    1,    1,    0 ),
-              'MONTH'           => array(  68,    1,    1,    0 ),
-              'YEAR'            => array(  69,    1,    1,    0 ),
-              'WEEKDAY'         => array(  70,   -1,    1,    0 ),
-              'HOUR'            => array(  71,    1,    1,    0 ),
-              'MINUTE'          => array(  72,    1,    1,    0 ),
-              'SECOND'          => array(  73,    1,    1,    0 ),
-              'NOW'             => array(  74,    0,    1,    1 ),
-              'AREAS'           => array(  75,    1,    0,    1 ),
-              'ROWS'            => array(  76,    1,    0,    1 ),
-              'COLUMNS'         => array(  77,    1,    0,    1 ),
-              'OFFSET'          => array(  78,   -1,    0,    1 ),
-              'SEARCH'          => array(  82,   -1,    1,    0 ),
-              'TRANSPOSE'       => array(  83,    1,    1,    0 ),
-              'TYPE'            => array(  86,    1,    1,    0 ),
-              'ATAN2'           => array(  97,    2,    1,    0 ),
-              'ASIN'            => array(  98,    1,    1,    0 ),
-              'ACOS'            => array(  99,    1,    1,    0 ),
-              'CHOOSE'          => array( 100,   -1,    1,    0 ),
-              'HLOOKUP'         => array( 101,   -1,    0,    0 ),
-              'VLOOKUP'         => array( 102,   -1,    0,    0 ),
-              'ISREF'           => array( 105,    1,    0,    0 ),
-              'LOG'             => array( 109,   -1,    1,    0 ),
-              'CHAR'            => array( 111,    1,    1,    0 ),
-              'LOWER'           => array( 112,    1,    1,    0 ),
-              'UPPER'           => array( 113,    1,    1,    0 ),
-              'PROPER'          => array( 114,    1,    1,    0 ),
-              'LEFT'            => array( 115,   -1,    1,    0 ),
-              'RIGHT'           => array( 116,   -1,    1,    0 ),
-              'EXACT'           => array( 117,    2,    1,    0 ),
-              'TRIM'            => array( 118,    1,    1,    0 ),
-              'REPLACE'         => array( 119,    4,    1,    0 ),
-              'SUBSTITUTE'      => array( 120,   -1,    1,    0 ),
-              'CODE'            => array( 121,    1,    1,    0 ),
-              'FIND'            => array( 124,   -1,    1,    0 ),
-              'CELL'            => array( 125,   -1,    0,    1 ),
-              'ISERR'           => array( 126,    1,    1,    0 ),
-              'ISTEXT'          => array( 127,    1,    1,    0 ),
-              'ISNUMBER'        => array( 128,    1,    1,    0 ),
-              'ISBLANK'         => array( 129,    1,    1,    0 ),
-              'T'               => array( 130,    1,    0,    0 ),
-              'N'               => array( 131,    1,    0,    0 ),
-              'DATEVALUE'       => array( 140,    1,    1,    0 ),
-              'TIMEVALUE'       => array( 141,    1,    1,    0 ),
-              'SLN'             => array( 142,    3,    1,    0 ),
-              'SYD'             => array( 143,    4,    1,    0 ),
-              'DDB'             => array( 144,   -1,    1,    0 ),
-              'INDIRECT'        => array( 148,   -1,    1,    1 ),
-              'CALL'            => array( 150,   -1,    1,    0 ),
-              'CLEAN'           => array( 162,    1,    1,    0 ),
-              'MDETERM'         => array( 163,    1,    2,    0 ),
-              'MINVERSE'        => array( 164,    1,    2,    0 ),
-              'MMULT'           => array( 165,    2,    2,    0 ),
-              'IPMT'            => array( 167,   -1,    1,    0 ),
-              'PPMT'            => array( 168,   -1,    1,    0 ),
-              'COUNTA'          => array( 169,   -1,    0,    0 ),
-              'PRODUCT'         => array( 183,   -1,    0,    0 ),
-              'FACT'            => array( 184,    1,    1,    0 ),
-              'DPRODUCT'        => array( 189,    3,    0,    0 ),
-              'ISNONTEXT'       => array( 190,    1,    1,    0 ),
-              'STDEVP'          => array( 193,   -1,    0,    0 ),
-              'VARP'            => array( 194,   -1,    0,    0 ),
-              'DSTDEVP'         => array( 195,    3,    0,    0 ),
-              'DVARP'           => array( 196,    3,    0,    0 ),
-              'TRUNC'           => array( 197,   -1,    1,    0 ),
-              'ISLOGICAL'       => array( 198,    1,    1,    0 ),
-              'DCOUNTA'         => array( 199,    3,    0,    0 ),
-              'ROUNDUP'         => array( 212,    2,    1,    0 ),
-              'ROUNDDOWN'       => array( 213,    2,    1,    0 ),
-              'RANK'            => array( 216,   -1,    0,    0 ),
-              'ADDRESS'         => array( 219,   -1,    1,    0 ),
-              'DAYS360'         => array( 220,   -1,    1,    0 ),
-              'TODAY'           => array( 221,    0,    1,    1 ),
-              'VDB'             => array( 222,   -1,    1,    0 ),
-              'MEDIAN'          => array( 227,   -1,    0,    0 ),
-              'SUMPRODUCT'      => array( 228,   -1,    2,    0 ),
-              'SINH'            => array( 229,    1,    1,    0 ),
-              'COSH'            => array( 230,    1,    1,    0 ),
-              'TANH'            => array( 231,    1,    1,    0 ),
-              'ASINH'           => array( 232,    1,    1,    0 ),
-              'ACOSH'           => array( 233,    1,    1,    0 ),
-              'ATANH'           => array( 234,    1,    1,    0 ),
-              'DGET'            => array( 235,    3,    0,    0 ),
-              'INFO'            => array( 244,    1,    1,    1 ),
-              'DB'              => array( 247,   -1,    1,    0 ),
-              'FREQUENCY'       => array( 252,    2,    0,    0 ),
-              'ERROR.TYPE'      => array( 261,    1,    1,    0 ),
-              'REGISTER.ID'     => array( 267,   -1,    1,    0 ),
-              'AVEDEV'          => array( 269,   -1,    0,    0 ),
-              'BETADIST'        => array( 270,   -1,    1,    0 ),
-              'GAMMALN'         => array( 271,    1,    1,    0 ),
-              'BETAINV'         => array( 272,   -1,    1,    0 ),
-              'BINOMDIST'       => array( 273,    4,    1,    0 ),
-              'CHIDIST'         => array( 274,    2,    1,    0 ),
-              'CHIINV'          => array( 275,    2,    1,    0 ),
-              'COMBIN'          => array( 276,    2,    1,    0 ),
-              'CONFIDENCE'      => array( 277,    3,    1,    0 ),
-              'CRITBINOM'       => array( 278,    3,    1,    0 ),
-              'EVEN'            => array( 279,    1,    1,    0 ),
-              'EXPONDIST'       => array( 280,    3,    1,    0 ),
-              'FDIST'           => array( 281,    3,    1,    0 ),
-              'FINV'            => array( 282,    3,    1,    0 ),
-              'FISHER'          => array( 283,    1,    1,    0 ),
-              'FISHERINV'       => array( 284,    1,    1,    0 ),
-              'FLOOR'           => array( 285,    2,    1,    0 ),
-              'GAMMADIST'       => array( 286,    4,    1,    0 ),
-              'GAMMAINV'        => array( 287,    3,    1,    0 ),
-              'CEILING'         => array( 288,    2,    1,    0 ),
-              'HYPGEOMDIST'     => array( 289,    4,    1,    0 ),
-              'LOGNORMDIST'     => array( 290,    3,    1,    0 ),
-              'LOGINV'          => array( 291,    3,    1,    0 ),
-              'NEGBINOMDIST'    => array( 292,    3,    1,    0 ),
-              'NORMDIST'        => array( 293,    4,    1,    0 ),
-              'NORMSDIST'       => array( 294,    1,    1,    0 ),
-              'NORMINV'         => array( 295,    3,    1,    0 ),
-              'NORMSINV'        => array( 296,    1,    1,    0 ),
-              'STANDARDIZE'     => array( 297,    3,    1,    0 ),
-              'ODD'             => array( 298,    1,    1,    0 ),
-              'PERMUT'          => array( 299,    2,    1,    0 ),
-              'POISSON'         => array( 300,    3,    1,    0 ),
-              'TDIST'           => array( 301,    3,    1,    0 ),
-              'WEIBULL'         => array( 302,    4,    1,    0 ),
-              'SUMXMY2'         => array( 303,    2,    2,    0 ),
-              'SUMX2MY2'        => array( 304,    2,    2,    0 ),
-              'SUMX2PY2'        => array( 305,    2,    2,    0 ),
-              'CHITEST'         => array( 306,    2,    2,    0 ),
-              'CORREL'          => array( 307,    2,    2,    0 ),
-              'COVAR'           => array( 308,    2,    2,    0 ),
-              'FORECAST'        => array( 309,    3,    2,    0 ),
-              'FTEST'           => array( 310,    2,    2,    0 ),
-              'INTERCEPT'       => array( 311,    2,    2,    0 ),
-              'PEARSON'         => array( 312,    2,    2,    0 ),
-              'RSQ'             => array( 313,    2,    2,    0 ),
-              'STEYX'           => array( 314,    2,    2,    0 ),
-              'SLOPE'           => array( 315,    2,    2,    0 ),
-              'TTEST'           => array( 316,    4,    2,    0 ),
-              'PROB'            => array( 317,   -1,    2,    0 ),
-              'DEVSQ'           => array( 318,   -1,    0,    0 ),
-              'GEOMEAN'         => array( 319,   -1,    0,    0 ),
-              'HARMEAN'         => array( 320,   -1,    0,    0 ),
-              'SUMSQ'           => array( 321,   -1,    0,    0 ),
-              'KURT'            => array( 322,   -1,    0,    0 ),
-              'SKEW'            => array( 323,   -1,    0,    0 ),
-              'ZTEST'           => array( 324,   -1,    0,    0 ),
-              'LARGE'           => array( 325,    2,    0,    0 ),
-              'SMALL'           => array( 326,    2,    0,    0 ),
-              'QUARTILE'        => array( 327,    2,    0,    0 ),
-              'PERCENTILE'      => array( 328,    2,    0,    0 ),
-              'PERCENTRANK'     => array( 329,   -1,    0,    0 ),
-              'MODE'            => array( 330,   -1,    2,    0 ),
-              'TRIMMEAN'        => array( 331,    2,    0,    0 ),
-              'TINV'            => array( 332,    2,    1,    0 ),
-              'CONCATENATE'     => array( 336,   -1,    1,    0 ),
-              'POWER'           => array( 337,    2,    1,    0 ),
-              'RADIANS'         => array( 342,    1,    1,    0 ),
-              'DEGREES'         => array( 343,    1,    1,    0 ),
-              'SUBTOTAL'        => array( 344,   -1,    0,    0 ),
-              'SUMIF'           => array( 345,   -1,    0,    0 ),
-              'COUNTIF'         => array( 346,    2,    0,    0 ),
-              'COUNTBLANK'      => array( 347,    1,    0,    0 ),
-              'ROMAN'           => array( 354,   -1,    1,    0 )
-              );
-    }
-
-    /**
-    * Convert a token to the proper ptg value.
-    *
-    * @access private
-    * @param mixed $token The token to convert.
-    * @return mixed the converted token on success. PEAR_Error if the token
-    *               is not recognized
-    */
-    function _convert($token)
-    {
-        if (preg_match("/^\"[^\"]{0,255}\"$/", $token)) {
-            return $this->_convertString($token);
-
-        } elseif (is_numeric($token)) {
-            return $this->_convertNumber($token);
-
-        // match references like A1 or $A$1
-        } elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$token)) {
-            return $this->_convertRef2d($token);
-
-        // match external references like Sheet1!A1 or Sheet1:Sheet2!A1
-        } elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z](\d+)$/u",$token)) {
-            return $this->_convertRef3d($token);
-
-        // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1
-        } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z](\d+)$/u",$token)) {
-            return $this->_convertRef3d($token);
-
-        // match ranges like A1:B2
-        } elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\:(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/",$token)) {
-            return $this->_convertRange2d($token);
-
-        // match ranges like A1..B2
-        } elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/",$token)) {
-            return $this->_convertRange2d($token);
-
-        // match external ranges like Sheet1!A1 or Sheet1:Sheet2!A1:B2
-        } elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?(\d+)\:([A-Ia-i]?[A-Za-z])?(\d+)$/u",$token)) {
-            return $this->_convertRange3d($token);
-
-        // match external ranges like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1:B2
-        } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?(\d+)\:([A-Ia-i]?[A-Za-z])?(\d+)$/u",$token)) {
-            return $this->_convertRange3d($token);
-
-        // operators (including parentheses)
-        } elseif (isset($this->ptg[$token])) {
-            return pack("C", $this->ptg[$token]);
-
-        // commented so argument number can be processed correctly. See toReversePolish().
-        /*elseif (preg_match("/[A-Z0-9\xc0-\xdc\.]+/",$token))
-        {
-            return($this->_convertFunction($token,$this->_func_args));
-        }*/
-
-        // if it's an argument, ignore the token (the argument remains)
-        } elseif ($token == 'arg') {
-            return '';
-        }
-        // TODO: use real error codes
-        return $this->raiseError("Unknown token $token");
-    }
-
-    /**
-    * Convert a number token to ptgInt or ptgNum
-    *
-    * @access private
-    * @param mixed $num an integer or double for conversion to its ptg value
-    */
-    function _convertNumber($num)
-    {
-        // Integer in the range 0..2**16-1
-        if ((preg_match("/^\d+$/", $num)) and ($num <= 65535)) {
-            return pack("Cv", $this->ptg['ptgInt'], $num);
-        } else { // A float
-            if ($this->_byte_order) { // if it's Big Endian
-                $num = strrev($num);
-            }
-            return pack("Cd", $this->ptg['ptgNum'], $num);
-        }
-    }
-
-    /**
-    * Convert a string token to ptgStr
-    *
-    * @access private
-    * @param string $string A string for conversion to its ptg value.
-    * @return mixed the converted token on success. PEAR_Error if the string
-    *               is longer than 255 characters.
-    */
-    function _convertString($string)
-    {
-        // chop away beggining and ending quotes
-        $string = substr($string, 1, strlen($string) - 2);
-        if (strlen($string) > 255) {
-            return $this->raiseError("String is too long");
-        }
-
-        if ($this->_BIFF_version == 0x0500) {
-            return pack("CC", $this->ptg['ptgStr'], strlen($string)).$string;
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $encoding = 0;   // TODO: Unicode support
-            return pack("CCC", $this->ptg['ptgStr'], strlen($string), $encoding).$string;
-        }
-    }
-
-    /**
-    * Convert a function to a ptgFunc or ptgFuncVarV depending on the number of
-    * args that it takes.
-    *
-    * @access private
-    * @param string  $token    The name of the function for convertion to ptg value.
-    * @param integer $num_args The number of arguments the function receives.
-    * @return string The packed ptg for the function
-    */
-    function _convertFunction($token, $num_args)
-    {
-        $args     = $this->_functions[$token][1];
-        $volatile = $this->_functions[$token][3];
-
-        // Fixed number of args eg. TIME($i,$j,$k).
-        if ($args >= 0) {
-            return pack("Cv", $this->ptg['ptgFuncV'], $this->_functions[$token][0]);
-        }
-        // Variable number of args eg. SUM($i,$j,$k, ..).
-        if ($args == -1) {
-            return pack("CCv", $this->ptg['ptgFuncVarV'], $num_args, $this->_functions[$token][0]);
-        }
-    }
-
-    /**
-    * Convert an Excel range such as A1:D4 to a ptgRefV.
-    *
-    * @access private
-    * @param string $range An Excel range in the A1:A2 or A1..A2 format.
-    */
-    function _convertRange2d($range, $class=0)
-    {
-
-        // TODO: possible class value 0,1,2 check Formula.pm
-        // Split the range into 2 cell refs
-        if (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\:([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) {
-            list($cell1, $cell2) = split(':', $range);
-        } elseif (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\.\.([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) {
-            list($cell1, $cell2) = split('\.\.', $range);
-
-        } else {
-            // TODO: use real error codes
-            return $this->raiseError("Unknown range separator", 0, PEAR_ERROR_DIE);
-        }
-
-        // Convert the cell references
-        $cell_array1 = $this->_cellToPackedRowcol($cell1);
-        if (PEAR::isError($cell_array1)) {
-            return $cell_array1;
-        }
-        list($row1, $col1) = $cell_array1;
-        $cell_array2 = $this->_cellToPackedRowcol($cell2);
-        if (PEAR::isError($cell_array2)) {
-            return $cell_array2;
-        }
-        list($row2, $col2) = $cell_array2;
-
-        // The ptg value depends on the class of the ptg.
-        if ($class == 0) {
-            $ptgArea = pack("C", $this->ptg['ptgArea']);
-        } elseif ($class == 1) {
-            $ptgArea = pack("C", $this->ptg['ptgAreaV']);
-        } elseif ($class == 2) {
-            $ptgArea = pack("C", $this->ptg['ptgAreaA']);
-        } else {
-            // TODO: use real error codes
-            return $this->raiseError("Unknown class $class", 0, PEAR_ERROR_DIE);
-        }
-        return $ptgArea . $row1 . $row2 . $col1. $col2;
-    }
-
-    /**
-    * Convert an Excel 3d range such as "Sheet1!A1:D4" or "Sheet1:Sheet2!A1:D4" to
-    * a ptgArea3d.
-    *
-    * @access private
-    * @param string $token An Excel range in the Sheet1!A1:A2 format.
-    * @return mixed The packed ptgArea3d token on success, PEAR_Error on failure.
-    */
-    function _convertRange3d($token)
-    {
-        $class = 2; // as far as I know, this is magick.
-
-        // Split the ref at the ! symbol
-        list($ext_ref, $range) = split('!', $token);
-
-        // Convert the external reference part (different for BIFF8)
-        if ($this->_BIFF_version == 0x0500) {
-            $ext_ref = $this->_packExtRef($ext_ref);
-            if (PEAR::isError($ext_ref)) {
-                return $ext_ref;
-            }
-        } elseif ($this->_BIFF_version == 0x0600) {
-             $ext_ref = $this->_getRefIndex($ext_ref);
-             if (PEAR::isError($ext_ref)) {
-                 return $ext_ref;
-             }
-        }
-
-        // Split the range into 2 cell refs
-        list($cell1, $cell2) = split(':', $range);
-
-        // Convert the cell references
-        if (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/", $cell1)) {
-            $cell_array1 = $this->_cellToPackedRowcol($cell1);
-            if (PEAR::isError($cell_array1)) {
-                return $cell_array1;
-            }
-            list($row1, $col1) = $cell_array1;
-            $cell_array2 = $this->_cellToPackedRowcol($cell2);
-            if (PEAR::isError($cell_array2)) {
-                return $cell_array2;
-            }
-            list($row2, $col2) = $cell_array2;
-        } else { // It's a rows range (like 26:27)
-             $cells_array = $this->_rangeToPackedRange($cell1.':'.$cell2);
-             if (PEAR::isError($cells_array)) {
-                 return $cells_array;
-             }
-             list($row1, $col1, $row2, $col2) = $cells_array;
-        }
-
-        // The ptg value depends on the class of the ptg.
-        if ($class == 0) {
-            $ptgArea = pack("C", $this->ptg['ptgArea3d']);
-        } elseif ($class == 1) {
-            $ptgArea = pack("C", $this->ptg['ptgArea3dV']);
-        } elseif ($class == 2) {
-            $ptgArea = pack("C", $this->ptg['ptgArea3dA']);
-        } else {
-            return $this->raiseError("Unknown class $class", 0, PEAR_ERROR_DIE);
-        }
-
-        return $ptgArea . $ext_ref . $row1 . $row2 . $col1. $col2;
-    }
-
-    /**
-    * Convert an Excel reference such as A1, $B2, C$3 or $D$4 to a ptgRefV.
-    *
-    * @access private
-    * @param string $cell An Excel cell reference
-    * @return string The cell in packed() format with the corresponding ptg
-    */
-    function _convertRef2d($cell)
-    {
-        $class = 2; // as far as I know, this is magick.
-
-        // Convert the cell reference
-        $cell_array = $this->_cellToPackedRowcol($cell);
-        if (PEAR::isError($cell_array)) {
-            return $cell_array;
-        }
-        list($row, $col) = $cell_array;
-
-        // The ptg value depends on the class of the ptg.
-        if ($class == 0) {
-            $ptgRef = pack("C", $this->ptg['ptgRef']);
-        } elseif ($class == 1) {
-            $ptgRef = pack("C", $this->ptg['ptgRefV']);
-        } elseif ($class == 2) {
-            $ptgRef = pack("C", $this->ptg['ptgRefA']);
-        } else {
-            // TODO: use real error codes
-            return $this->raiseError("Unknown class $class");
-        }
-        return $ptgRef.$row.$col;
-    }
-
-    /**
-    * Convert an Excel 3d reference such as "Sheet1!A1" or "Sheet1:Sheet2!A1" to a
-    * ptgRef3d.
-    *
-    * @access private
-    * @param string $cell An Excel cell reference
-    * @return mixed The packed ptgRef3d token on success, PEAR_Error on failure.
-    */
-    function _convertRef3d($cell)
-    {
-        $class = 2; // as far as I know, this is magick.
-
-        // Split the ref at the ! symbol
-        list($ext_ref, $cell) = split('!', $cell);
-
-        // Convert the external reference part (different for BIFF8)
-        if ($this->_BIFF_version == 0x0500) {
-            $ext_ref = $this->_packExtRef($ext_ref);
-            if (PEAR::isError($ext_ref)) {
-                return $ext_ref;
-            }
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $ext_ref = $this->_getRefIndex($ext_ref);
-            if (PEAR::isError($ext_ref)) {
-                return $ext_ref;
-            }
-        }
-
-        // Convert the cell reference part
-        list($row, $col) = $this->_cellToPackedRowcol($cell);
-
-        // The ptg value depends on the class of the ptg.
-        if ($class == 0) {
-            $ptgRef = pack("C", $this->ptg['ptgRef3d']);
-        } elseif ($class == 1) {
-            $ptgRef = pack("C", $this->ptg['ptgRef3dV']);
-        } elseif ($class == 2) {
-            $ptgRef = pack("C", $this->ptg['ptgRef3dA']);
-        } else {
-            return $this->raiseError("Unknown class $class", 0, PEAR_ERROR_DIE);
-        }
-
-        return $ptgRef . $ext_ref. $row . $col;
-    }
-
-    /**
-    * Convert the sheet name part of an external reference, for example "Sheet1" or
-    * "Sheet1:Sheet2", to a packed structure.
-    *
-    * @access private
-    * @param string $ext_ref The name of the external reference
-    * @return string The reference index in packed() format
-    */
-    function _packExtRef($ext_ref)
-    {
-        $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading  ' if any.
-        $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any.
-
-        // Check if there is a sheet range eg., Sheet1:Sheet2.
-        if (preg_match("/:/", $ext_ref)) {
-            list($sheet_name1, $sheet_name2) = split(':', $ext_ref);
-
-            $sheet1 = $this->_getSheetIndex($sheet_name1);
-            if ($sheet1 == -1) {
-                return $this->raiseError("Unknown sheet name $sheet_name1 in formula");
-            }
-            $sheet2 = $this->_getSheetIndex($sheet_name2);
-            if ($sheet2 == -1) {
-                return $this->raiseError("Unknown sheet name $sheet_name2 in formula");
-            }
-
-            // Reverse max and min sheet numbers if necessary
-            if ($sheet1 > $sheet2) {
-                list($sheet1, $sheet2) = array($sheet2, $sheet1);
-            }
-        } else { // Single sheet name only.
-            $sheet1 = $this->_getSheetIndex($ext_ref);
-            if ($sheet1 == -1) {
-                return $this->raiseError("Unknown sheet name $ext_ref in formula");
-            }
-            $sheet2 = $sheet1;
-        }
-
-        // References are stored relative to 0xFFFF.
-        $offset = -1 - $sheet1;
-
-        return pack('vdvv', $offset, 0x00, $sheet1, $sheet2);
-    }
-
-    /**
-    * Look up the REF index that corresponds to an external sheet name
-    * (or range). If it doesn't exist yet add it to the workbook's references
-    * array. It assumes all sheet names given must exist.
-    *
-    * @access private
-    * @param string $ext_ref The name of the external reference
-    * @return mixed The reference index in packed() format on success,
-    *               PEAR_Error on failure
-    */
-    function _getRefIndex($ext_ref)
-    {
-        $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading  ' if any.
-        $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any.
-
-        // Check if there is a sheet range eg., Sheet1:Sheet2.
-        if (preg_match("/:/", $ext_ref)) {
-            list($sheet_name1, $sheet_name2) = split(':', $ext_ref);
-
-            $sheet1 = $this->_getSheetIndex($sheet_name1);
-            if ($sheet1 == -1) {
-                return $this->raiseError("Unknown sheet name $sheet_name1 in formula");
-            }
-            $sheet2 = $this->_getSheetIndex($sheet_name2);
-            if ($sheet2 == -1) {
-                return $this->raiseError("Unknown sheet name $sheet_name2 in formula");
-            }
-
-            // Reverse max and min sheet numbers if necessary
-            if ($sheet1 > $sheet2) {
-                list($sheet1, $sheet2) = array($sheet2, $sheet1);
-            }
-        } else { // Single sheet name only.
-            $sheet1 = $this->_getSheetIndex($ext_ref);
-            if ($sheet1 == -1) {
-                return $this->raiseError("Unknown sheet name $ext_ref in formula");
-            }
-            $sheet2 = $sheet1;
-        }
-
-        // assume all references belong to this document
-        $supbook_index = 0x00;
-        $ref = pack('vvv', $supbook_index, $sheet1, $sheet2);
-        $total_references = count($this->_references);
-        $index = -1;
-        for ($i = 0; $i < $total_references; $i++) {
-            if ($ref == $this->_references[$i]) {
-                $index = $i;
-                break;
-            }
-        }
-        // if REF was not found add it to references array
-        if ($index == -1) {
-            $this->_references[$total_references] = $ref;
-            $index = $total_references;
-        }
-
-        return pack('v', $index);
-    }
-
-    /**
-    * Look up the index that corresponds to an external sheet name. The hash of
-    * sheet names is updated by the addworksheet() method of the
-    * Spreadsheet_Excel_Writer_Workbook class.
-    *
-    * @access private
-    * @return integer The sheet index, -1 if the sheet was not found
-    */
-    function _getSheetIndex($sheet_name)
-    {
-        if (!isset($this->_ext_sheets[$sheet_name])) {
-            return -1;
-        } else {
-            return $this->_ext_sheets[$sheet_name];
-        }
-    }
-
-    /**
-    * This method is used to update the array of sheet names. It is
-    * called by the addWorksheet() method of the
-    * Spreadsheet_Excel_Writer_Workbook class.
-    *
-    * @access public
-    * @see Spreadsheet_Excel_Writer_Workbook::addWorksheet()
-    * @param string  $name  The name of the worksheet being added
-    * @param integer $index The index of the worksheet being added
-    */
-    function setExtSheet($name, $index)
-    {
-        $this->_ext_sheets[$name] = $index;
-    }
-
-    /**
-    * pack() row and column into the required 3 or 4 byte format.
-    *
-    * @access private
-    * @param string $cell The Excel cell reference to be packed
-    * @return array Array containing the row and column in packed() format
-    */
-    function _cellToPackedRowcol($cell)
-    {
-        $cell = strtoupper($cell);
-        list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell);
-        if ($col >= 256) {
-            return $this->raiseError("Column in: $cell greater than 255");
-        }
-        // FIXME: change for BIFF8
-        if ($row >= 16384) {
-            return $this->raiseError("Row in: $cell greater than 16384 ");
-        }
-
-        // Set the high bits to indicate if row or col are relative.
-        if ($this->_BIFF_version == 0x0500) {
-            $row    |= $col_rel << 14;
-            $row    |= $row_rel << 15;
-            $col     = pack('C', $col);
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $col    |= $col_rel << 14;
-            $col    |= $row_rel << 15;
-            $col     = pack('v', $col);
-        }
-        $row     = pack('v', $row);
-
-        return array($row, $col);
-    }
-
-    /**
-    * pack() row range into the required 3 or 4 byte format.
-    * Just using maximum col/rows, which is probably not the correct solution
-    *
-    * @access private
-    * @param string $range The Excel range to be packed
-    * @return array Array containing (row1,col1,row2,col2) in packed() format
-    */
-    function _rangeToPackedRange($range)
-    {
-        preg_match('/(\$)?(\d+)\:(\$)?(\d+)/', $range, $match);
-        // return absolute rows if there is a $ in the ref
-        $row1_rel = empty($match[1]) ? 1 : 0;
-        $row1     = $match[2];
-        $row2_rel = empty($match[3]) ? 1 : 0;
-        $row2     = $match[4];
-        // Convert 1-index to zero-index
-        $row1--;
-        $row2--;
-        // Trick poor inocent Excel
-        $col1 = 0;
-        $col2 = 16383; // FIXME: maximum possible value for Excel 5 (change this!!!)
-
-        // FIXME: this changes for BIFF8
-        if (($row1 >= 16384) or ($row2 >= 16384)) {
-            return $this->raiseError("Row in: $range greater than 16384 ");
-        }
-
-        // Set the high bits to indicate if rows are relative.
-        if ($this->_BIFF_version == 0x0500) {
-            $row1    |= $row1_rel << 14; // FIXME: probably a bug
-            $row2    |= $row2_rel << 15;
-            $col1     = pack('C', $col1);
-            $col2     = pack('C', $col2);
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $col1    |= $row1_rel << 15;
-            $col2    |= $row2_rel << 15;
-            $col1     = pack('v', $col1);
-            $col2     = pack('v', $col2);
-        }
-        $row1     = pack('v', $row1);
-        $row2     = pack('v', $row2);
-
-        return array($row1, $col1, $row2, $col2);
-    }
-
-    /**
-    * Convert an Excel cell reference such as A1 or $B2 or C$3 or $D$4 to a zero
-    * indexed row and column number. Also returns two (0,1) values to indicate
-    * whether the row or column are relative references.
-    *
-    * @access private
-    * @param string $cell The Excel cell reference in A1 format.
-    * @return array
-    */
-    function _cellToRowcol($cell)
-    {
-        preg_match('/(\$)?([A-I]?[A-Z])(\$)?(\d+)/',$cell,$match);
-        // return absolute column if there is a $ in the ref
-        $col_rel = empty($match[1]) ? 1 : 0;
-        $col_ref = $match[2];
-        $row_rel = empty($match[3]) ? 1 : 0;
-        $row     = $match[4];
-
-        // Convert base26 column string to a number.
-        $expn   = strlen($col_ref) - 1;
-        $col    = 0;
-        $col_ref_length = strlen($col_ref);
-        for ($i = 0; $i < $col_ref_length; $i++) {
-            $col += (ord($col_ref{$i}) - ord('A') + 1) * pow(26, $expn);
-            $expn--;
-        }
-
-        // Convert 1-index to zero-index
-        $row--;
-        $col--;
-
-        return array($row, $col, $row_rel, $col_rel);
-    }
-
-    /**
-    * Advance to the next valid token.
-    *
-    * @access private
-    */
-    function _advance()
-    {
-        $i = $this->_current_char;
-        $formula_length = strlen($this->_formula);
-        // eat up white spaces
-        if ($i < $formula_length) {
-            while ($this->_formula{$i} == " ") {
-                $i++;
-            }
-
-            if ($i < ($formula_length - 1)) {
-                $this->_lookahead = $this->_formula{$i+1};
-            }
-            $token = '';
-        }
-
-        while ($i < $formula_length) {
-            $token .= $this->_formula{$i};
-            if ($i < ($formula_length - 1)) {
-                $this->_lookahead = $this->_formula{$i+1};
-            } else {
-                $this->_lookahead = '';
-            }
-
-            if ($this->_match($token) != '') {
-                //if ($i < strlen($this->_formula) - 1) {
-                //    $this->_lookahead = $this->_formula{$i+1};
-                //}
-                $this->_current_char = $i + 1;
-                $this->_current_token = $token;
-                return 1;
-            }
-
-            if ($i < ($formula_length - 2)) {
-                $this->_lookahead = $this->_formula{$i+2};
-            } else { // if we run out of characters _lookahead becomes empty
-                $this->_lookahead = '';
-            }
-            $i++;
-        }
-        //die("Lexical error ".$this->_current_char);
-    }
-
-    /**
-    * Checks if it's a valid token.
-    *
-    * @access private
-    * @param mixed $token The token to check.
-    * @return mixed       The checked token or false on failure
-    */
-    function _match($token)
-    {
-        switch($token) {
-            case SPREADSHEET_EXCEL_WRITER_ADD:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_SUB:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_MUL:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_DIV:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_OPEN:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_CLOSE:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_COMA:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_SEMICOLON:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_GT:
-                if ($this->_lookahead == '=') { // it's a GE token
-                    break;
-                }
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_LT:
-                // it's a LE or a NE token
-                if (($this->_lookahead == '=') or ($this->_lookahead == '>')) {
-                    break;
-                }
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_GE:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_LE:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_EQ:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_NE:
-                return $token;
-                break;
-            case SPREADSHEET_EXCEL_WRITER_CONCAT:
-                return $token;
-                break;
-            default:
-                // if it's a reference
-                if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and
-                   !preg_match("/[0-9]/",$this->_lookahead) and
-                   ($this->_lookahead != ':') and ($this->_lookahead != '.') and
-                   ($this->_lookahead != '!'))
-                {
-                    return $token;
-                }
-                // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1)
-                elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z][0-9]+$/u",$token) and
-                       !preg_match("/[0-9]/",$this->_lookahead) and
-                       ($this->_lookahead != ':') and ($this->_lookahead != '.'))
-                {
-                    return $token;
-                }
-                // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1)
-                elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z][0-9]+$/u",$token) and
-                       !preg_match("/[0-9]/",$this->_lookahead) and
-                       ($this->_lookahead != ':') and ($this->_lookahead != '.'))
-                {
-                    return $token;
-                }
-                // if it's a range (A1:A2)
-                elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and
-                       !preg_match("/[0-9]/",$this->_lookahead))
-                {
-                    return $token;
-                }
-                // if it's a range (A1..A2)
-                elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and
-                       !preg_match("/[0-9]/",$this->_lookahead))
-                {
-                    return $token;
-                }
-                // If it's an external range like Sheet1!A1 or Sheet1:Sheet2!A1:B2
-                elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$token) and
-                       !preg_match("/[0-9]/",$this->_lookahead))
-                {
-                    return $token;
-                }
-                // If it's an external range like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1:B2
-                elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$token) and
-                       !preg_match("/[0-9]/",$this->_lookahead))
-                {
-                    return $token;
-                }
-                // If it's a number (check that it's not a sheet name or range)
-                elseif (is_numeric($token) and
-                        (!is_numeric($token.$this->_lookahead) or ($this->_lookahead == '')) and
-                        ($this->_lookahead != '!') and ($this->_lookahead != ':'))
-                {
-                    return $token;
-                }
-                // If it's a string (of maximum 255 characters)
-                elseif (preg_match("/^\"[^\"]{0,255}\"$/",$token))
-                {
-                    return $token;
-                }
-                // if it's a function call
-                elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "("))
-                {
-                    return $token;
-                }
-                return '';
-        }
-    }
-
-    /**
-    * The parsing method. It parses a formula.
-    *
-    * @access public
-    * @param string $formula The formula to parse, without the initial equal
-    *                        sign (=).
-    * @return mixed true on success, PEAR_Error on failure
-    */
-    function parse($formula)
-    {
-        $this->_current_char = 0;
-        $this->_formula      = $formula;
-        $this->_lookahead    = $formula{1};
-        $this->_advance();
-        $this->_parse_tree   = $this->_condition();
-        if (PEAR::isError($this->_parse_tree)) {
-            return $this->_parse_tree;
-        }
-        return true;
-    }
-
-    /**
-    * It parses a condition. It assumes the following rule:
-    * Cond -> Expr [(">" | "<") Expr]
-    *
-    * @access private
-    * @return mixed The parsed ptg'd tree on success, PEAR_Error on failure
-    */
-    function _condition()
-    {
-        $result = $this->_expression();
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_LT) {
-            $this->_advance();
-            $result2 = $this->_expression();
-            if (PEAR::isError($result2)) {
-                return $result2;
-            }
-            $result = $this->_createTree('ptgLT', $result, $result2);
-        } elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_GT) {
-            $this->_advance();
-            $result2 = $this->_expression();
-            if (PEAR::isError($result2)) {
-                return $result2;
-            }
-            $result = $this->_createTree('ptgGT', $result, $result2);
-        } elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_LE) {
-            $this->_advance();
-            $result2 = $this->_expression();
-            if (PEAR::isError($result2)) {
-                return $result2;
-            }
-            $result = $this->_createTree('ptgLE', $result, $result2);
-        } elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_GE) {
-            $this->_advance();
-            $result2 = $this->_expression();
-            if (PEAR::isError($result2)) {
-                return $result2;
-            }
-            $result = $this->_createTree('ptgGE', $result, $result2);
-        } elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_EQ) {
-            $this->_advance();
-            $result2 = $this->_expression();
-            if (PEAR::isError($result2)) {
-                return $result2;
-            }
-            $result = $this->_createTree('ptgEQ', $result, $result2);
-        } elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_NE) {
-            $this->_advance();
-            $result2 = $this->_expression();
-            if (PEAR::isError($result2)) {
-                return $result2;
-            }
-            $result = $this->_createTree('ptgNE', $result, $result2);
-        } elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_CONCAT) {
-            $this->_advance();
-            $result2 = $this->_expression();
-            if (PEAR::isError($result2)) {
-                return $result2;
-        }
-            $result = $this->_createTree('ptgConcat', $result, $result2);
-        }
-        return $result;
-    }
-
-    /**
-    * It parses a expression. It assumes the following rule:
-    * Expr -> Term [("+" | "-") Term]
-    *      -> "string"
-    *      -> "-" Term
-    *
-    * @access private
-    * @return mixed The parsed ptg'd tree on success, PEAR_Error on failure
-    */
-    function _expression()
-    {
-        // If it's a string return a string node
-        if (preg_match("/^\"[^\"]{0,255}\"$/", $this->_current_token)) {
-            $result = $this->_createTree($this->_current_token, '', '');
-            $this->_advance();
-            return $result;
-        } elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_SUB) {
-            // catch "-" Term
-            $this->_advance();
-            $result2 = $this->_expression();
-            $result = $this->_createTree('ptgUminus', $result2, '');
-            return $result;
-        }
-        $result = $this->_term();
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        while (($this->_current_token == SPREADSHEET_EXCEL_WRITER_ADD) or
-               ($this->_current_token == SPREADSHEET_EXCEL_WRITER_SUB)) {
-        /**/
-            if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_ADD) {
-                $this->_advance();
-                $result2 = $this->_term();
-                if (PEAR::isError($result2)) {
-                    return $result2;
-                }
-                $result = $this->_createTree('ptgAdd', $result, $result2);
-            } else {
-                $this->_advance();
-                $result2 = $this->_term();
-                if (PEAR::isError($result2)) {
-                    return $result2;
-                }
-                $result = $this->_createTree('ptgSub', $result, $result2);
-            }
-        }
-        return $result;
-    }
-
-    /**
-    * This function just introduces a ptgParen element in the tree, so that Excel
-    * doesn't get confused when working with a parenthesized formula afterwards.
-    *
-    * @access private
-    * @see _fact()
-    * @return array The parsed ptg'd tree
-    */
-    function _parenthesizedExpression()
-    {
-        $result = $this->_createTree('ptgParen', $this->_expression(), '');
-        return $result;
-    }
-
-    /**
-    * It parses a term. It assumes the following rule:
-    * Term -> Fact [("*" | "/") Fact]
-    *
-    * @access private
-    * @return mixed The parsed ptg'd tree on success, PEAR_Error on failure
-    */
-    function _term()
-    {
-        $result = $this->_fact();
-        if (PEAR::isError($result)) {
-            return $result;
-        }
-        while (($this->_current_token == SPREADSHEET_EXCEL_WRITER_MUL) or
-               ($this->_current_token == SPREADSHEET_EXCEL_WRITER_DIV)) {
-        /**/
-            if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_MUL) {
-                $this->_advance();
-                $result2 = $this->_fact();
-                if (PEAR::isError($result2)) {
-                    return $result2;
-                }
-                $result = $this->_createTree('ptgMul', $result, $result2);
-            } else {
-                $this->_advance();
-                $result2 = $this->_fact();
-                if (PEAR::isError($result2)) {
-                    return $result2;
-                }
-                $result = $this->_createTree('ptgDiv', $result, $result2);
-            }
-        }
-        return $result;
-    }
-
-    /**
-    * It parses a factor. It assumes the following rule:
-    * Fact -> ( Expr )
-    *       | CellRef
-    *       | CellRange
-    *       | Number
-    *       | Function
-    *
-    * @access private
-    * @return mixed The parsed ptg'd tree on success, PEAR_Error on failure
-    */
-    function _fact()
-    {
-        if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_OPEN) {
-            $this->_advance();         // eat the "("
-            $result = $this->_parenthesizedExpression();
-            if ($this->_current_token != SPREADSHEET_EXCEL_WRITER_CLOSE) {
-                return $this->raiseError("')' token expected.");
-            }
-            $this->_advance();         // eat the ")"
-            return $result;
-        }
-        // if it's a reference
-        if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$this->_current_token))
-        {
-            $result = $this->_createTree($this->_current_token, '', '');
-            $this->_advance();
-            return $result;
-        }
-        // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1)
-        elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z][0-9]+$/u",$this->_current_token))
-        {
-            $result = $this->_createTree($this->_current_token, '', '');
-            $this->_advance();
-            return $result;
-        }
-        // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1)
-        elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z][0-9]+$/u",$this->_current_token))
-        {
-            $result = $this->_createTree($this->_current_token, '', '');
-            $this->_advance();
-            return $result;
-        }
-        // if it's a range
-        elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token) or
-                preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token))
-        {
-            $result = $this->_current_token;
-            $this->_advance();
-            return $result;
-        }
-        // If it's an external range (Sheet1!A1 or Sheet1!A1:B2)
-        elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$this->_current_token))
-        {
-            $result = $this->_current_token;
-            $this->_advance();
-            return $result;
-        }
-        // If it's an external range ('Sheet1'!A1 or 'Sheet1'!A1:B2)
-        elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$this->_current_token))
-        {
-            $result = $this->_current_token;
-            $this->_advance();
-            return $result;
-        }
-        elseif (is_numeric($this->_current_token))
-        {
-            $result = $this->_createTree($this->_current_token, '', '');
-            $this->_advance();
-            return $result;
-        }
-        // if it's a function call
-        elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$this->_current_token))
-        {
-            $result = $this->_func();
-            return $result;
-        }
-        return $this->raiseError("Syntax error: ".$this->_current_token.
-                                 ", lookahead: ".$this->_lookahead.
-                                 ", current char: ".$this->_current_char);
-    }
-
-    /**
-    * It parses a function call. It assumes the following rule:
-    * Func -> ( Expr [,Expr]* )
-    *
-    * @access private
-    * @return mixed The parsed ptg'd tree on success, PEAR_Error on failure
-    */
-    function _func()
-    {
-        $num_args = 0; // number of arguments received
-        $function = strtoupper($this->_current_token);
-        $result   = ''; // initialize result
-        $this->_advance();
-        $this->_advance();         // eat the "("
-        while ($this->_current_token != ')') {
-        /**/
-            if ($num_args > 0) {
-                if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_COMA or
-                    $this->_current_token == SPREADSHEET_EXCEL_WRITER_SEMICOLON)
-                {
-                    $this->_advance();  // eat the "," or ";"
-                } else {
-                    return $this->raiseError("Syntax error: comma expected in ".
-                                      "function $function, arg #{$num_args}");
-                }
-                $result2 = $this->_condition();
-                if (PEAR::isError($result2)) {
-                    return $result2;
-                }
-                $result = $this->_createTree('arg', $result, $result2);
-            } else { // first argument
-                $result2 = $this->_condition();
-                if (PEAR::isError($result2)) {
-                    return $result2;
-                }
-                $result = $this->_createTree('arg', '', $result2);
-            }
-            $num_args++;
-        }
-        if (!isset($this->_functions[$function])) {
-            return $this->raiseError("Function $function() doesn't exist");
-        }
-        $args = $this->_functions[$function][1];
-        // If fixed number of args eg. TIME($i,$j,$k). Check that the number of args is valid.
-        if (($args >= 0) and ($args != $num_args)) {
-            return $this->raiseError("Incorrect number of arguments in function $function() ");
-        }
-
-        $result = $this->_createTree($function, $result, $num_args);
-        $this->_advance();         // eat the ")"
-        return $result;
-    }
-
-    /**
-    * Creates a tree. In fact an array which may have one or two arrays (sub-trees)
-    * as elements.
-    *
-    * @access private
-    * @param mixed $value The value of this node.
-    * @param mixed $left  The left array (sub-tree) or a final node.
-    * @param mixed $right The right array (sub-tree) or a final node.
-    * @return array A tree
-    */
-    function _createTree($value, $left, $right)
-    {
-        return array('value' => $value, 'left' => $left, 'right' => $right);
-    }
-
-    /**
-    * Builds a string containing the tree in reverse polish notation (What you
-    * would use in a HP calculator stack).
-    * The following tree:
-    *
-    *    +
-    *   / \
-    *  2   3
-    *
-    * produces: "23+"
-    *
-    * The following tree:
-    *
-    *    +
-    *   / \
-    *  3   *
-    *     / \
-    *    6   A1
-    *
-    * produces: "36A1*+"
-    *
-    * In fact all operands, functions, references, etc... are written as ptg's
-    *
-    * @access public
-    * @param array $tree The optional tree to convert.
-    * @return string The tree in reverse polish notation
-    */
-    function toReversePolish($tree = array())
-    {
-        $polish = ""; // the string we are going to return
-        if (empty($tree)) { // If it's the first call use _parse_tree
-            $tree = $this->_parse_tree;
-        }
-        if (is_array($tree['left'])) {
-            $converted_tree = $this->toReversePolish($tree['left']);
-            if (PEAR::isError($converted_tree)) {
-                return $converted_tree;
-            }
-            $polish .= $converted_tree;
-        } elseif ($tree['left'] != '') { // It's a final node
-            $converted_tree = $this->_convert($tree['left']);
-            if (PEAR::isError($converted_tree)) {
-                return $converted_tree;
-            }
-            $polish .= $converted_tree;
-        }
-        if (is_array($tree['right'])) {
-            $converted_tree = $this->toReversePolish($tree['right']);
-            if (PEAR::isError($converted_tree)) {
-                return $converted_tree;
-            }
-            $polish .= $converted_tree;
-        } elseif ($tree['right'] != '') { // It's a final node
-            $converted_tree = $this->_convert($tree['right']);
-            if (PEAR::isError($converted_tree)) {
-                return $converted_tree;
-            }
-            $polish .= $converted_tree;
-        }
-        // if it's a function convert it here (so we can set it's arguments)
-        if (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/",$tree['value']) and
-            !preg_match('/^([A-Ia-i]?[A-Za-z])(\d+)$/',$tree['value']) and
-            !preg_match("/^[A-Ia-i]?[A-Za-z](\d+)\.\.[A-Ia-i]?[A-Za-z](\d+)$/",$tree['value']) and
-            !is_numeric($tree['value']) and
-            !isset($this->ptg[$tree['value']]))
-        {
-            // left subtree for a function is always an array.
-            if ($tree['left'] != '') {
-                $left_tree = $this->toReversePolish($tree['left']);
-            } else {
-                $left_tree = '';
-            }
-            if (PEAR::isError($left_tree)) {
-                return $left_tree;
-            }
-            // add it's left subtree and return.
-            return $left_tree.$this->_convertFunction($tree['value'], $tree['right']);
-        } else {
-            $converted_tree = $this->_convert($tree['value']);
-            if (PEAR::isError($converted_tree)) {
-                return $converted_tree;
-            }
-        }
-        $polish .= $converted_tree;
-        return $polish;
-    }
-}
-?>

+ 0 - 230
main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Validator.php

@@ -1,230 +0,0 @@
-<?php
-/*
-*  Module written by Herman Kuiper <herman@ozuzo.net>
-*
-*  License Information:
-*
-*    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
-*    Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
-*
-*    This library is free software; you can redistribute it and/or
-*    modify it under the terms of the GNU Lesser General Public
-*    License as published by the Free Software Foundation; either
-*    version 2.1 of the License, or (at your option) any later version.
-*
-*    This library is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-*    Lesser General Public License for more details.
-*
-*    You should have received a copy of the GNU Lesser General Public
-*    License along with this library; if not, write to the Free Software
-*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-//require_once('PEAR.php');
-
-// Possible operator types
-
-/*
-FIXME: change prefixes
-*/
-define("OP_BETWEEN",    0x00);
-define("OP_NOTBETWEEN", 0x01);
-define("OP_EQUAL",      0x02);
-define("OP_NOTEQUAL",   0x03);
-define("OP_GT",         0x04);
-define("OP_LT",         0x05);
-define("OP_GTE",        0x06);
-define("OP_LTE",        0x07);
-
-/**
-* Baseclass for generating Excel DV records (validations)
-*
-* @author   Herman Kuiper
-* @category FileFormats
-* @package  Spreadsheet_Excel_Writer
-*/
-class Spreadsheet_Excel_Writer_Validator
-{
-   var $_type;
-   var $_style;
-   var $_fixedList;
-   var $_blank;
-   var $_incell;
-   var $_showprompt;
-   var $_showerror;
-   var $_title_prompt;
-   var $_descr_prompt;
-   var $_title_error;
-   var $_descr_error;
-   var $_operator;
-   var $_formula1;
-   var $_formula2;
-    /**
-    * The parser from the workbook. Used to parse validation formulas also
-    * @var Spreadsheet_Excel_Writer_Parser
-    */
-    var $_parser;
-
-    function Spreadsheet_Excel_Writer_Validator(&$parser)
-    {
-        $this->_parser       = $parser;
-        $this->_type         = 0x01; // FIXME: add method for setting datatype
-        $this->_style        = 0x00;
-        $this->_fixedList    = false;
-        $this->_blank        = false;
-        $this->_incell       = false;
-        $this->_showprompt   = false;
-        $this->_showerror    = true;
-        $this->_title_prompt = "\x00";
-        $this->_descr_prompt = "\x00";
-        $this->_title_error  = "\x00";
-        $this->_descr_error  = "\x00";
-        $this->_operator     = 0x00; // default is equal
-        $this->_formula1    = '';
-        $this->_formula2    = '';
-    }
-
-   function setPrompt($promptTitle = "\x00", $promptDescription = "\x00", $showPrompt = true)
-   {
-      $this->_showprompt = $showPrompt;
-      $this->_title_prompt = $promptTitle;
-      $this->_descr_prompt = $promptDescription;
-   }
-
-   function setError($errorTitle = "\x00", $errorDescription = "\x00", $showError = true)
-   {
-      $this->_showerror = $showError;
-      $this->_title_error = $errorTitle;
-      $this->_descr_error = $errorDescription;
-   }
-
-   function allowBlank()
-   {
-      $this->_blank = true;
-   }
-
-   function onInvalidStop()
-   {
-      $this->_style = 0x00;
-   }
-
-    function onInvalidWarn()
-    {
-        $this->_style = 0x01;
-    }
-
-    function onInvalidInfo()
-    {
-        $this->_style = 0x02;
-    }
-
-    function setFormula1($formula)
-    {
-        // Parse the formula using the parser in Parser.php
-        $error = $this->_parser->parse($formula);
-        if (PEAR::isError($error)) {
-            return $this->_formula1;
-        }
-
-        $this->_formula1 = $this->_parser->toReversePolish();
-        if (PEAR::isError($this->_formula1)) {
-            return $this->_formula1;
-        }
-        return true;
-    }
-
-    function setFormula2($formula)
-    {
-        // Parse the formula using the parser in Parser.php
-        $error = $this->_parser->parse($formula);
-        if (PEAR::isError($error)) {
-            return $this->_formula2;
-        }
-
-        $this->_formula2 = $this->_parser->toReversePolish();
-        if (PEAR::isError($this->_formula2)) {
-            return $this->_formula2;
-        }
-        return true;
-    }
-
-    function _getOptions()
-    {
-        $options = $this->_type;
-        $options |= $this->_style << 3;
-        if ($this->_fixedList) {
-            $options |= 0x80;
-        }
-        if ($this->_blank) {
-            $options |= 0x100;
-        }
-        if (!$this->_incell) {
-            $options |= 0x200;
-        }
-        if ($this->_showprompt) {
-            $options |= 0x40000;
-        }
-        if ($this->_showerror) {
-            $options |= 0x80000;
-        }
-      $options |= $this->_operator << 20;
-
-      return $options;
-   }
-
-   function _getData()
-   {
-      $title_prompt_len = strlen($this->_title_prompt);
-      $descr_prompt_len = strlen($this->_descr_prompt);
-      $title_error_len = strlen($this->_title_error);
-      $descr_error_len = strlen($this->_descr_error);
-
-      $formula1_size = strlen($this->_formula1);
-      $formula2_size = strlen($this->_formula2);
-
-      $data  = pack("V", $this->_getOptions());
-      $data .= pack("vC", $title_prompt_len, 0x00) . $this->_title_prompt;
-      $data .= pack("vC", $title_error_len, 0x00) . $this->_title_error;
-      $data .= pack("vC", $descr_prompt_len, 0x00) . $this->_descr_prompt;
-      $data .= pack("vC", $descr_error_len, 0x00) . $this->_descr_error;
-
-      $data .= pack("vv", $formula1_size, 0x0000) . $this->_formula1;
-      $data .= pack("vv", $formula2_size, 0x0000) . $this->_formula2;
-
-      return $data;
-   }
-}
-
-/*class Spreadsheet_Excel_Writer_Validation_List extends Spreadsheet_Excel_Writer_Validation
-{
-   function Spreadsheet_Excel_Writer_Validation_list()
-   {
-      parent::Spreadsheet_Excel_Writer_Validation();
-      $this->_type = 0x03;
-   }
-
-   function setList($source, $incell = true)
-   {
-      $this->_incell = $incell;
-      $this->_fixedList = true;
-
-      $source = implode("\x00", $source);
-      $this->_formula1 = pack("CCC", 0x17, strlen($source), 0x0c) . $source;
-   }
-
-   function setRow($row, $col1, $col2, $incell = true)
-   {
-      $this->_incell = $incell;
-      //$this->_formula1 = ...;
-   }
-
-   function setCol($col, $row1, $row2, $incell = true)
-   {
-      $this->_incell = $incell;
-      //$this->_formula1 = ...;
-   }
-}*/
-
-?>

+ 0 - 1591
main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Workbook.php

@@ -1,1591 +0,0 @@
-<?php
-/*
-*  Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
-*
-*  The majority of this is _NOT_ my code.  I simply ported it from the
-*  PERL Spreadsheet::WriteExcel module.
-*
-*  The author of the Spreadsheet::WriteExcel module is John McNamara
-*  <jmcnamara@cpan.org>
-*
-*  I _DO_ maintain this code, and John McNamara has nothing to do with the
-*  porting of this code to PHP.  Any questions directly related to this
-*  class library should be directed to me.
-*
-*  License Information:
-*
-*    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
-*    Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
-*
-*    This library is free software; you can redistribute it and/or
-*    modify it under the terms of the GNU Lesser General Public
-*    License as published by the Free Software Foundation; either
-*    version 2.1 of the License, or (at your option) any later version.
-*
-*    This library is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-*    Lesser General Public License for more details.
-*
-*    You should have received a copy of the GNU Lesser General Public
-*    License along with this library; if not, write to the Free Software
-*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer/Format.php';
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer/BIFFwriter.php';
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer/Worksheet.php';
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer/Parser.php';
-require_once api_get_path(LIBRARY_PATH).'pear/OLE/PPS/Root.php';
-require_once api_get_path(LIBRARY_PATH).'pear/OLE/PPS/File.php';
-
-/**
-* Class for generating Excel Spreadsheets
-*
-* @author   Xavier Noguer <xnoguer@rezebra.com>
-* @category FileFormats
-* @package  Spreadsheet_Excel_Writer
-*/
-
-class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwriter
-{
-    /**
-    * Filename for the Workbook
-    * @var string
-    */
-    var $_filename;
-
-    /**
-    * Formula parser
-    * @var object Parser
-    */
-    var $_parser;
-
-    /**
-    * Flag for 1904 date system (0 => base date is 1900, 1 => base date is 1904)
-    * @var integer
-    */
-    var $_1904;
-
-    /**
-    * The active worksheet of the workbook (0 indexed)
-    * @var integer
-    */
-    var $_activesheet;
-
-    /**
-    * 1st displayed worksheet in the workbook (0 indexed)
-    * @var integer
-    */
-    var $_firstsheet;
-
-    /**
-    * Number of workbook tabs selected
-    * @var integer
-    */
-    var $_selected;
-
-    /**
-    * Index for creating adding new formats to the workbook
-    * @var integer
-    */
-    var $_xf_index;
-
-    /**
-    * Flag for preventing close from being called twice.
-    * @var integer
-    * @see close()
-    */
-    var $_fileclosed;
-
-    /**
-    * The BIFF file size for the workbook.
-    * @var integer
-    * @see _calcSheetOffsets()
-    */
-    var $_biffsize;
-
-    /**
-    * The default sheetname for all sheets created.
-    * @var string
-    */
-    var $_sheetname;
-
-    /**
-    * The default XF format.
-    * @var object Format
-    */
-    var $_tmp_format;
-
-    /**
-    * Array containing references to all of this workbook's worksheets
-    * @var array
-    */
-    var $_worksheets;
-
-    /**
-    * Array of sheetnames for creating the EXTERNSHEET records
-    * @var array
-    */
-    var $_sheetnames;
-
-    /**
-    * Array containing references to all of this workbook's formats
-    * @var array
-    */
-    var $_formats;
-
-    /**
-    * Array containing the colour palette
-    * @var array
-    */
-    var $_palette;
-
-    /**
-    * The default format for URLs.
-    * @var object Format
-    */
-    var $_url_format;
-
-    /**
-    * The codepage indicates the text encoding used for strings
-    * @var integer
-    */
-    var $_codepage;
-
-    /**
-    * The country code used for localization
-    * @var integer
-    */
-    var $_country_code;
-
-    /**
-    * number of bytes for sizeinfo of strings
-    * @var integer
-    */
-    var $_string_sizeinfo_size;
-
-    /**
-    * Class constructor
-    *
-    * @param string filename for storing the workbook. "-" for writing to stdout.
-    * @access public
-    */
-    function Spreadsheet_Excel_Writer_Workbook($filename)
-    {
-        // It needs to call its parent's constructor explicitly
-        $this->Spreadsheet_Excel_Writer_BIFFwriter();
-
-        $this->_filename         = $filename;
-        $this->_parser           =& new Spreadsheet_Excel_Writer_Parser($this->_byte_order, $this->_BIFF_version);
-        $this->_1904             = 0;
-        $this->_activesheet      = 0;
-        $this->_firstsheet       = 0;
-        $this->_selected         = 0;
-        $this->_xf_index         = 16; // 15 style XF's and 1 cell XF.
-        $this->_fileclosed       = 0;
-        $this->_biffsize         = 0;
-        $this->_sheetname        = 'Sheet';
-        $this->_tmp_format       =& new Spreadsheet_Excel_Writer_Format($this->_BIFF_version);
-        $this->_worksheets       = array();
-        $this->_sheetnames       = array();
-        $this->_formats          = array();
-        $this->_palette          = array();
-        $this->_codepage         = 0x04E4; // FIXME: should change for BIFF8
-        $this->_country_code     = -1;
-        $this->_string_sizeinfo  = 3;
-
-        // Add the default format for hyperlinks
-        $this->_url_format =& $this->addFormat(array('color' => 'blue', 'underline' => 1));
-        $this->_str_total       = 0;
-        $this->_str_unique      = 0;
-        $this->_str_table       = array();
-        $this->_setPaletteXl97();
-    }
-
-    /**
-    * Calls finalization methods.
-    * This method should always be the last one to be called on every workbook
-    *
-    * @access public
-    * @return mixed true on success. PEAR_Error on failure
-    */
-    function close()
-    {
-        if ($this->_fileclosed) { // Prevent close() from being called twice.
-            return true;
-        }
-        $res = $this->_storeWorkbook();
-        if ($this->isError($res)) {
-            return $this->raiseError($res->getMessage());
-        }
-        $this->_fileclosed = 1;
-        return true;
-    }
-
-    /**
-    * An accessor for the _worksheets[] array
-    * Returns an array of the worksheet objects in a workbook
-    * It actually calls to worksheets()
-    *
-    * @access public
-    * @see worksheets()
-    * @return array
-    */
-    function sheets()
-    {
-        return $this->worksheets();
-    }
-
-    /**
-    * An accessor for the _worksheets[] array.
-    * Returns an array of the worksheet objects in a workbook
-    *
-    * @access public
-    * @return array
-    */
-    function worksheets()
-    {
-        return $this->_worksheets;
-    }
-
-    /**
-    * Sets the BIFF version.
-    * This method exists just to access experimental functionality
-    * from BIFF8. It will be deprecated !
-    * Only possible value is 8 (Excel 97/2000).
-    * For any other value it fails silently.
-    *
-    * @access public
-    * @param integer $version The BIFF version
-    */
-    function setVersion($version)
-    {
-        if ($version == 8) { // only accept version 8
-            $version = 0x0600;
-            $this->_BIFF_version = $version;
-            // change BIFFwriter limit for CONTINUE records
-            $this->_limit = 8228;
-            $this->_tmp_format->_BIFF_version = $version;
-            $this->_url_format->_BIFF_version = $version;
-            $this->_parser->_BIFF_version = $version;
-            $this->_codepage = 0x04B0;
-
-            $total_worksheets = count($this->_worksheets);
-            // change version for all worksheets too
-            for ($i = 0; $i < $total_worksheets; $i++) {
-                $this->_worksheets[$i]->_BIFF_version = $version;
-            }
-
-            $total_formats = count($this->_formats);
-            // change version for all formats too
-            for ($i = 0; $i < $total_formats; $i++) {
-                $this->_formats[$i]->_BIFF_version = $version;
-            }
-        }
-    }
-
-    /**
-    * Set the country identifier for the workbook
-    *
-    * @access public
-    * @param integer $code Is the international calling country code for the
-    *                      chosen country.
-    */
-    function setCountry($code)
-    {
-        $this->_country_code = $code;
-    }
-
-    /**
-    * Add a new worksheet to the Excel workbook.
-    * If no name is given the name of the worksheet will be Sheeti$i, with
-    * $i in [1..].
-    *
-    * @access public
-    * @param string $name the optional name of the worksheet
-    * @return mixed reference to a worksheet object on success, PEAR_Error
-    *               on failure
-    */
-    function &addWorksheet($name = '')
-    {
-        $index     = count($this->_worksheets);
-        $sheetname = $this->_sheetname;
-
-        if ($name == '') {
-            $name = $sheetname.($index+1);
-        }
-
-        // Check that sheetname is <= 31 chars (Excel limit before BIFF8).
-        if ($this->_BIFF_version != 0x0600)
-        {
-            if (strlen($name) > 31) {
-                return $this->raiseError("Sheetname $name must be <= 31 chars");
-            }
-        }
-
-        // Check that the worksheet name doesn't already exist: a fatal Excel error.
-        $total_worksheets = count($this->_worksheets);
-        for ($i = 0; $i < $total_worksheets; $i++) {
-            if ($this->_worksheets[$i]->getName() == $name) {
-                return $this->raiseError("Worksheet '$name' already exists");
-            }
-        }
-
-        $worksheet = new Spreadsheet_Excel_Writer_Worksheet($this->_BIFF_version,
-                                   $name, $index,
-                                   $this->_activesheet, $this->_firstsheet,
-                                   $this->_str_total, $this->_str_unique,
-                                   $this->_str_table, $this->_url_format,
-                                   $this->_parser, $this->_tmp_dir);
-
-        $this->_worksheets[$index] = &$worksheet;    // Store ref for iterator
-        $this->_sheetnames[$index] = $name;          // Store EXTERNSHEET names
-        $this->_parser->setExtSheet($name, $index);  // Register worksheet name with parser
-        return $worksheet;
-    }
-
-    /**
-    * Add a new format to the Excel workbook.
-    * Also, pass any properties to the Format constructor.
-    *
-    * @access public
-    * @param array $properties array with properties for initializing the format.
-    * @return &Spreadsheet_Excel_Writer_Format reference to an Excel Format
-    */
-    function &addFormat($properties = array())
-    {
-        $format = new Spreadsheet_Excel_Writer_Format($this->_BIFF_version, $this->_xf_index, $properties);
-        $this->_xf_index += 1;
-        $this->_formats[] = &$format;
-        return $format;
-    }
-
-    /**
-     * Create new validator.
-     *
-     * @access public
-     * @return &Spreadsheet_Excel_Writer_Validator reference to a Validator
-     */
-    function &addValidator()
-    {
-        include_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer/Validator.php';
-        /* FIXME: check for successful inclusion*/
-        $valid = new Spreadsheet_Excel_Writer_Validator($this->_parser);
-        return $valid;
-    }
-
-    /**
-    * Change the RGB components of the elements in the colour palette.
-    *
-    * @access public
-    * @param integer $index colour index
-    * @param integer $red   red RGB value [0-255]
-    * @param integer $green green RGB value [0-255]
-    * @param integer $blue  blue RGB value [0-255]
-    * @return integer The palette index for the custom color
-    */
-    function setCustomColor($index, $red, $green, $blue)
-    {
-        // Match a HTML #xxyyzz style parameter
-        /*if (defined $_[1] and $_[1] =~ /^#(\w\w)(\w\w)(\w\w)/ ) {
-            @_ = ($_[0], hex $1, hex $2, hex $3);
-        }*/
-
-        // Check that the colour index is the right range
-        if ($index < 8 or $index > 64) {
-            // TODO: assign real error codes
-            return $this->raiseError("Color index $index outside range: 8 <= index <= 64");
-        }
-
-        // Check that the colour components are in the right range
-        if (($red   < 0 or $red   > 255) ||
-            ($green < 0 or $green > 255) ||
-            ($blue  < 0 or $blue  > 255))
-        {
-            return $this->raiseError("Color component outside range: 0 <= color <= 255");
-        }
-
-        $index -= 8; // Adjust colour index (wingless dragonfly)
-
-        // Set the RGB value
-        $this->_palette[$index] = array($red, $green, $blue, 0);
-        return($index + 8);
-    }
-
-    /**
-    * Sets the colour palette to the Excel 97+ default.
-    *
-    * @access private
-    */
-    function _setPaletteXl97()
-    {
-        $this->_palette = array(
-                           array(0x00, 0x00, 0x00, 0x00),   // 8
-                           array(0xff, 0xff, 0xff, 0x00),   // 9
-                           array(0xff, 0x00, 0x00, 0x00),   // 10
-                           array(0x00, 0xff, 0x00, 0x00),   // 11
-                           array(0x00, 0x00, 0xff, 0x00),   // 12
-                           array(0xff, 0xff, 0x00, 0x00),   // 13
-                           array(0xff, 0x00, 0xff, 0x00),   // 14
-                           array(0x00, 0xff, 0xff, 0x00),   // 15
-                           array(0x80, 0x00, 0x00, 0x00),   // 16
-                           array(0x00, 0x80, 0x00, 0x00),   // 17
-                           array(0x00, 0x00, 0x80, 0x00),   // 18
-                           array(0x80, 0x80, 0x00, 0x00),   // 19
-                           array(0x80, 0x00, 0x80, 0x00),   // 20
-                           array(0x00, 0x80, 0x80, 0x00),   // 21
-                           array(0xc0, 0xc0, 0xc0, 0x00),   // 22
-                           array(0x80, 0x80, 0x80, 0x00),   // 23
-                           array(0x99, 0x99, 0xff, 0x00),   // 24
-                           array(0x99, 0x33, 0x66, 0x00),   // 25
-                           array(0xff, 0xff, 0xcc, 0x00),   // 26
-                           array(0xcc, 0xff, 0xff, 0x00),   // 27
-                           array(0x66, 0x00, 0x66, 0x00),   // 28
-                           array(0xff, 0x80, 0x80, 0x00),   // 29
-                           array(0x00, 0x66, 0xcc, 0x00),   // 30
-                           array(0xcc, 0xcc, 0xff, 0x00),   // 31
-                           array(0x00, 0x00, 0x80, 0x00),   // 32
-                           array(0xff, 0x00, 0xff, 0x00),   // 33
-                           array(0xff, 0xff, 0x00, 0x00),   // 34
-                           array(0x00, 0xff, 0xff, 0x00),   // 35
-                           array(0x80, 0x00, 0x80, 0x00),   // 36
-                           array(0x80, 0x00, 0x00, 0x00),   // 37
-                           array(0x00, 0x80, 0x80, 0x00),   // 38
-                           array(0x00, 0x00, 0xff, 0x00),   // 39
-                           array(0x00, 0xcc, 0xff, 0x00),   // 40
-                           array(0xcc, 0xff, 0xff, 0x00),   // 41
-                           array(0xcc, 0xff, 0xcc, 0x00),   // 42
-                           array(0xff, 0xff, 0x99, 0x00),   // 43
-                           array(0x99, 0xcc, 0xff, 0x00),   // 44
-                           array(0xff, 0x99, 0xcc, 0x00),   // 45
-                           array(0xcc, 0x99, 0xff, 0x00),   // 46
-                           array(0xff, 0xcc, 0x99, 0x00),   // 47
-                           array(0x33, 0x66, 0xff, 0x00),   // 48
-                           array(0x33, 0xcc, 0xcc, 0x00),   // 49
-                           array(0x99, 0xcc, 0x00, 0x00),   // 50
-                           array(0xff, 0xcc, 0x00, 0x00),   // 51
-                           array(0xff, 0x99, 0x00, 0x00),   // 52
-                           array(0xff, 0x66, 0x00, 0x00),   // 53
-                           array(0x66, 0x66, 0x99, 0x00),   // 54
-                           array(0x96, 0x96, 0x96, 0x00),   // 55
-                           array(0x00, 0x33, 0x66, 0x00),   // 56
-                           array(0x33, 0x99, 0x66, 0x00),   // 57
-                           array(0x00, 0x33, 0x00, 0x00),   // 58
-                           array(0x33, 0x33, 0x00, 0x00),   // 59
-                           array(0x99, 0x33, 0x00, 0x00),   // 60
-                           array(0x99, 0x33, 0x66, 0x00),   // 61
-                           array(0x33, 0x33, 0x99, 0x00),   // 62
-                           array(0x33, 0x33, 0x33, 0x00),   // 63
-                         );
-    }
-
-    /**
-    * Assemble worksheets into a workbook and send the BIFF data to an OLE
-    * storage.
-    *
-    * @access private
-    * @return mixed true on success. PEAR_Error on failure
-    */
-    function _storeWorkbook()
-    {
-        if (count($this->_worksheets) == 0) {
-            return true;
-        }
-
-        // Ensure that at least one worksheet has been selected.
-        if ($this->_activesheet == 0) {
-            $this->_worksheets[0]->selected = 1;
-        }
-
-        // Calculate the number of selected worksheet tabs and call the finalization
-        // methods for each worksheet
-        $total_worksheets = count($this->_worksheets);
-        for ($i = 0; $i < $total_worksheets; $i++) {
-            if ($this->_worksheets[$i]->selected) {
-                $this->_selected++;
-            }
-            $this->_worksheets[$i]->close($this->_sheetnames);
-        }
-
-        // Add Workbook globals
-        $this->_storeBof(0x0005);
-        $this->_storeCodepage();
-        if ($this->_BIFF_version == 0x0600) {
-            $this->_storeWindow1();
-        }
-        if ($this->_BIFF_version == 0x0500) {
-            $this->_storeExterns();    // For print area and repeat rows
-        }
-        $this->_storeNames();      // For print area and repeat rows
-        if ($this->_BIFF_version == 0x0500) {
-            $this->_storeWindow1();
-        }
-        $this->_storeDatemode();
-        $this->_storeAllFonts();
-        $this->_storeAllNumFormats();
-        $this->_storeAllXfs();
-        $this->_storeAllStyles();
-        $this->_storePalette();
-        $this->_calcSheetOffsets();
-
-        // Add BOUNDSHEET records
-        for ($i = 0; $i < $total_worksheets; $i++) {
-            $this->_storeBoundsheet($this->_worksheets[$i]->name,$this->_worksheets[$i]->offset);
-        }
-
-        if ($this->_country_code != -1) {
-            $this->_storeCountry();
-        }
-
-        if ($this->_BIFF_version == 0x0600) {
-            //$this->_storeSupbookInternal();
-            /* TODO: store external SUPBOOK records and XCT and CRN records
-            in case of external references for BIFF8 */
-            //$this->_storeExternsheetBiff8();
-            $this->_storeSharedStringsTable();
-        }
-
-        // End Workbook globals
-        $this->_storeEof();
-
-        // Store the workbook in an OLE container
-        $res = $this->_storeOLEFile();
-        if ($this->isError($res)) {
-            return $this->raiseError($res->getMessage());
-        }
-        return true;
-    }
-
-    /**
-    * Store the workbook in an OLE container
-    *
-    * @access private
-    * @return mixed true on success. PEAR_Error on failure
-    */
-    function _storeOLEFile()
-    {
-        if($this->_BIFF_version == 0x0600) {
-            $OLE = new OLE_PPS_File(OLE::Asc2Ucs('Workbook'));
-        } else {
-            $OLE = new OLE_PPS_File(OLE::Asc2Ucs('Book'));
-        }
-        if ($this->_tmp_dir != '') {
-            $OLE->setTempDir($this->_tmp_dir);
-        }
-        $res = $OLE->init();
-        if ($this->isError($res)) {
-            return $this->raiseError("OLE Error: ".$res->getMessage());
-        }
-        $OLE->append($this->_data);
-
-        $total_worksheets = count($this->_worksheets);
-        for ($i = 0; $i < $total_worksheets; $i++) {
-            while ($tmp = $this->_worksheets[$i]->getData()) {
-                $OLE->append($tmp);
-            }
-        }
-
-        $root = new OLE_PPS_Root(time(), time(), array($OLE));
-        if ($this->_tmp_dir != '') {
-            $root->setTempDir($this->_tmp_dir);
-        }
-
-        $res = $root->save($this->_filename);
-        if ($this->isError($res)) {
-            return $this->raiseError("OLE Error: ".$res->getMessage());
-        }
-        return true;
-    }
-
-    /**
-    * Calculate offsets for Worksheet BOF records.
-    *
-    * @access private
-    */
-    function _calcSheetOffsets()
-    {
-        if ($this->_BIFF_version == 0x0600) {
-            $boundsheet_length = 12;  // fixed length for a BOUNDSHEET record
-        } else {
-            $boundsheet_length = 11;
-        }
-        $EOF               = 4;
-        $offset            = $this->_datasize;
-
-        if ($this->_BIFF_version == 0x0600) {
-            // add the length of the SST
-            /* TODO: check this works for a lot of strings (> 8224 bytes) */
-            $offset += $this->_calculateSharedStringsSizes();
-            if ($this->_country_code != -1) {
-                $offset += 8; // adding COUNTRY record
-            }
-            // add the lenght of SUPBOOK, EXTERNSHEET and NAME records
-            //$offset += 8; // FIXME: calculate real value when storing the records
-        }
-        $total_worksheets = count($this->_worksheets);
-        // add the length of the BOUNDSHEET records
-        for ($i = 0; $i < $total_worksheets; $i++) {
-            $offset += $boundsheet_length + strlen($this->_worksheets[$i]->name);
-        }
-        $offset += $EOF;
-
-        for ($i = 0; $i < $total_worksheets; $i++) {
-            $this->_worksheets[$i]->offset = $offset;
-            $offset += $this->_worksheets[$i]->_datasize;
-        }
-        $this->_biffsize = $offset;
-    }
-
-    /**
-    * Store the Excel FONT records.
-    *
-    * @access private
-    */
-    function _storeAllFonts()
-    {
-        // tmp_format is added by the constructor. We use this to write the default XF's
-        $format = $this->_tmp_format;
-        $font   = $format->getFont();
-
-        // Note: Fonts are 0-indexed. According to the SDK there is no index 4,
-        // so the following fonts are 0, 1, 2, 3, 5
-        //
-        for ($i = 1; $i <= 5; $i++){
-            $this->_append($font);
-        }
-
-        // Iterate through the XF objects and write a FONT record if it isn't the
-        // same as the default FONT and if it hasn't already been used.
-        //
-        $fonts = array();
-        $index = 6;                  // The first user defined FONT
-
-        $key = $format->getFontKey(); // The default font from _tmp_format
-        $fonts[$key] = 0;             // Index of the default font
-
-        $total_formats = count($this->_formats);
-        for ($i = 0; $i < $total_formats; $i++) {
-            $key = $this->_formats[$i]->getFontKey();
-            if (isset($fonts[$key])) {
-                // FONT has already been used
-                $this->_formats[$i]->font_index = $fonts[$key];
-            } else {
-                // Add a new FONT record
-                $fonts[$key]        = $index;
-                $this->_formats[$i]->font_index = $index;
-                $index++;
-                $font = $this->_formats[$i]->getFont();
-                $this->_append($font);
-            }
-        }
-    }
-
-    /**
-    * Store user defined numerical formats i.e. FORMAT records
-    *
-    * @access private
-    */
-    function _storeAllNumFormats()
-    {
-        // Leaning num_format syndrome
-        $hash_num_formats = array();
-        $num_formats      = array();
-        $index = 164;
-
-        // Iterate through the XF objects and write a FORMAT record if it isn't a
-        // built-in format type and if the FORMAT string hasn't already been used.
-        $total_formats = count($this->_formats);
-        for ($i = 0; $i < $total_formats; $i++) {
-            $num_format = $this->_formats[$i]->_num_format;
-
-            // Check if $num_format is an index to a built-in format.
-            // Also check for a string of zeros, which is a valid format string
-            // but would evaluate to zero.
-            //
-            if (!preg_match("/^0+\d/", $num_format)) {
-                if (preg_match("/^\d+$/", $num_format)) { // built-in format
-                    continue;
-                }
-            }
-
-            if (isset($hash_num_formats[$num_format])) {
-                // FORMAT has already been used
-                $this->_formats[$i]->_num_format = $hash_num_formats[$num_format];
-            } else{
-                // Add a new FORMAT
-                $hash_num_formats[$num_format]  = $index;
-                $this->_formats[$i]->_num_format = $index;
-                array_push($num_formats,$num_format);
-                $index++;
-            }
-        }
-
-        // Write the new FORMAT records starting from 0xA4
-        $index = 164;
-        foreach ($num_formats as $num_format) {
-            $this->_storeNumFormat($num_format,$index);
-            $index++;
-        }
-    }
-
-    /**
-    * Write all XF records.
-    *
-    * @access private
-    */
-    function _storeAllXfs()
-    {
-        // _tmp_format is added by the constructor. We use this to write the default XF's
-        // The default font index is 0
-        //
-        $format = $this->_tmp_format;
-        for ($i = 0; $i <= 14; $i++) {
-            $xf = $format->getXf('style'); // Style XF
-            $this->_append($xf);
-        }
-
-        $xf = $format->getXf('cell');      // Cell XF
-        $this->_append($xf);
-
-        // User defined XFs
-        $total_formats = count($this->_formats);
-        for ($i = 0; $i < $total_formats; $i++) {
-            $xf = $this->_formats[$i]->getXf('cell');
-            $this->_append($xf);
-        }
-    }
-
-    /**
-    * Write all STYLE records.
-    *
-    * @access private
-    */
-    function _storeAllStyles()
-    {
-        $this->_storeStyle();
-    }
-
-    /**
-    * Write the EXTERNCOUNT and EXTERNSHEET records. These are used as indexes for
-    * the NAME records.
-    *
-    * @access private
-    */
-    function _storeExterns()
-    {
-        // Create EXTERNCOUNT with number of worksheets
-        $this->_storeExterncount(count($this->_worksheets));
-
-        // Create EXTERNSHEET for each worksheet
-        foreach ($this->_sheetnames as $sheetname) {
-            $this->_storeExternsheet($sheetname);
-        }
-    }
-
-    /**
-    * Write the NAME record to define the print area and the repeat rows and cols.
-    *
-    * @access private
-    */
-    function _storeNames()
-    {
-        // Create the print area NAME records
-        $total_worksheets = count($this->_worksheets);
-        for ($i = 0; $i < $total_worksheets; $i++) {
-            // Write a Name record if the print area has been defined
-            if (isset($this->_worksheets[$i]->print_rowmin)) {
-                $this->_storeNameShort(
-                    $this->_worksheets[$i]->index,
-                    0x06, // NAME type
-                    $this->_worksheets[$i]->print_rowmin,
-                    $this->_worksheets[$i]->print_rowmax,
-                    $this->_worksheets[$i]->print_colmin,
-                    $this->_worksheets[$i]->print_colmax
-                    );
-            }
-        }
-
-        // Create the print title NAME records
-        $total_worksheets = count($this->_worksheets);
-        for ($i = 0; $i < $total_worksheets; $i++) {
-            $rowmin = $this->_worksheets[$i]->title_rowmin;
-            $rowmax = $this->_worksheets[$i]->title_rowmax;
-            $colmin = $this->_worksheets[$i]->title_colmin;
-            $colmax = $this->_worksheets[$i]->title_colmax;
-
-            // Determine if row + col, row, col or nothing has been defined
-            // and write the appropriate record
-            //
-            if (isset($rowmin) && isset($colmin)) {
-                // Row and column titles have been defined.
-                // Row title has been defined.
-                $this->_storeNameLong(
-                    $this->_worksheets[$i]->index,
-                    0x07, // NAME type
-                    $rowmin,
-                    $rowmax,
-                    $colmin,
-                    $colmax
-                    );
-            } elseif (isset($rowmin)) {
-                // Row title has been defined.
-                $this->_storeNameShort(
-                    $this->_worksheets[$i]->index,
-                    0x07, // NAME type
-                    $rowmin,
-                    $rowmax,
-                    0x00,
-                    0xff
-                    );
-            } elseif (isset($colmin)) {
-                // Column title has been defined.
-                $this->_storeNameShort(
-                    $this->_worksheets[$i]->index,
-                    0x07, // NAME type
-                    0x0000,
-                    0x3fff,
-                    $colmin,
-                    $colmax
-                    );
-            } else {
-                // Print title hasn't been defined.
-            }
-        }
-    }
-
-
-
-
-    /******************************************************************************
-    *
-    * BIFF RECORDS
-    *
-    */
-
-    /**
-    * Stores the CODEPAGE biff record.
-    *
-    * @access private
-    */
-    function _storeCodepage()
-    {
-        $record          = 0x0042;             // Record identifier
-        $length          = 0x0002;             // Number of bytes to follow
-        $cv              = $this->_codepage;   // The code page
-
-        $header          = pack('vv', $record, $length);
-        $data            = pack('v',  $cv);
-
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Write Excel BIFF WINDOW1 record.
-    *
-    * @access private
-    */
-    function _storeWindow1()
-    {
-        $record    = 0x003D;                 // Record identifier
-        $length    = 0x0012;                 // Number of bytes to follow
-
-        $xWn       = 0x0000;                 // Horizontal position of window
-        $yWn       = 0x0000;                 // Vertical position of window
-        $dxWn      = 0x25BC;                 // Width of window
-        $dyWn      = 0x1572;                 // Height of window
-
-        $grbit     = 0x0038;                 // Option flags
-        $ctabsel   = $this->_selected;       // Number of workbook tabs selected
-        $wTabRatio = 0x0258;                 // Tab to scrollbar ratio
-
-        $itabFirst = $this->_firstsheet;     // 1st displayed worksheet
-        $itabCur   = $this->_activesheet;    // Active worksheet
-
-        $header    = pack("vv",        $record, $length);
-        $data      = pack("vvvvvvvvv", $xWn, $yWn, $dxWn, $dyWn,
-                                       $grbit,
-                                       $itabCur, $itabFirst,
-                                       $ctabsel, $wTabRatio);
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Writes Excel BIFF BOUNDSHEET record.
-    * FIXME: inconsistent with BIFF documentation
-    *
-    * @param string  $sheetname Worksheet name
-    * @param integer $offset    Location of worksheet BOF
-    * @access private
-    */
-    function _storeBoundsheet($sheetname,$offset)
-    {
-        $record    = 0x0085;                    // Record identifier
-        if ($this->_BIFF_version == 0x0600) {
-            $length    = 0x08 + strlen($sheetname); // Number of bytes to follow
-        } else {
-            $length = 0x07 + strlen($sheetname); // Number of bytes to follow
-        }
-
-        $grbit     = 0x0000;                    // Visibility and sheet type
-        $cch       = strlen($sheetname);        // Length of sheet name
-
-        $header    = pack("vv",  $record, $length);
-        if ($this->_BIFF_version == 0x0600) {
-            $data      = pack("Vvv", $offset, $grbit, $cch);
-        } else {
-            $data      = pack("VvC", $offset, $grbit, $cch);
-        }
-        $this->_append($header.$data.$sheetname);
-    }
-
-    /**
-    * Write Internal SUPBOOK record
-    *
-    * @access private
-    */
-    function _storeSupbookInternal()
-    {
-        $record    = 0x01AE;   // Record identifier
-        $length    = 0x0004;   // Bytes to follow
-
-        $header    = pack("vv", $record, $length);
-        $data      = pack("vv", count($this->_worksheets), 0x0104);
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Writes the Excel BIFF EXTERNSHEET record. These references are used by
-    * formulas.
-    *
-    * @param string $sheetname Worksheet name
-    * @access private
-    */
-    function _storeExternsheetBiff8()
-    {
-        $total_references = count($this->_parser->_references);
-        $record   = 0x0017;                     // Record identifier
-        $length   = 2 + 6 * $total_references;  // Number of bytes to follow
-
-        $supbook_index = 0;           // FIXME: only using internal SUPBOOK record
-        $header           = pack("vv",  $record, $length);
-        $data             = pack('v', $total_references);
-        for ($i = 0; $i < $total_references; $i++) {
-            $data .= $this->_parser->_references[$i];
-        }
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Write Excel BIFF STYLE records.
-    *
-    * @access private
-    */
-    function _storeStyle()
-    {
-        $record    = 0x0293;   // Record identifier
-        $length    = 0x0004;   // Bytes to follow
-
-        $ixfe      = 0x8000;   // Index to style XF
-        $BuiltIn   = 0x00;     // Built-in style
-        $iLevel    = 0xff;     // Outline style level
-
-        $header    = pack("vv",  $record, $length);
-        $data      = pack("vCC", $ixfe, $BuiltIn, $iLevel);
-        $this->_append($header . $data);
-    }
-
-
-    /**
-    * Writes Excel FORMAT record for non "built-in" numerical formats.
-    *
-    * @param string  $format Custom format string
-    * @param integer $ifmt   Format index code
-    * @access private
-    */
-    function _storeNumFormat($format, $ifmt)
-    {
-        $record    = 0x041E;                      // Record identifier
-
-        if ($this->_BIFF_version == 0x0600) {
-            $length    = 5 + strlen($format);      // Number of bytes to follow
-            $encoding = 0x0;
-        } elseif ($this->_BIFF_version == 0x0500) {
-            $length    = 3 + strlen($format);      // Number of bytes to follow
-        }
-
-        $cch       = strlen($format);             // Length of format string
-
-        $header    = pack("vv", $record, $length);
-        if ($this->_BIFF_version == 0x0600) {
-            $data      = pack("vvC", $ifmt, $cch, $encoding);
-        } elseif ($this->_BIFF_version == 0x0500) {
-            $data      = pack("vC", $ifmt, $cch);
-        }
-        $this->_append($header . $data . $format);
-    }
-
-    /**
-    * Write DATEMODE record to indicate the date system in use (1904 or 1900).
-    *
-    * @access private
-    */
-    function _storeDatemode()
-    {
-        $record    = 0x0022;         // Record identifier
-        $length    = 0x0002;         // Bytes to follow
-
-        $f1904     = $this->_1904;   // Flag for 1904 date system
-
-        $header    = pack("vv", $record, $length);
-        $data      = pack("v", $f1904);
-        $this->_append($header . $data);
-    }
-
-
-    /**
-    * Write BIFF record EXTERNCOUNT to indicate the number of external sheet
-    * references in the workbook.
-    *
-    * Excel only stores references to external sheets that are used in NAME.
-    * The workbook NAME record is required to define the print area and the repeat
-    * rows and columns.
-    *
-    * A similar method is used in Worksheet.php for a slightly different purpose.
-    *
-    * @param integer $cxals Number of external references
-    * @access private
-    */
-    function _storeExterncount($cxals)
-    {
-        $record   = 0x0016;          // Record identifier
-        $length   = 0x0002;          // Number of bytes to follow
-
-        $header   = pack("vv", $record, $length);
-        $data     = pack("v",  $cxals);
-        $this->_append($header . $data);
-    }
-
-
-    /**
-    * Writes the Excel BIFF EXTERNSHEET record. These references are used by
-    * formulas. NAME record is required to define the print area and the repeat
-    * rows and columns.
-    *
-    * A similar method is used in Worksheet.php for a slightly different purpose.
-    *
-    * @param string $sheetname Worksheet name
-    * @access private
-    */
-    function _storeExternsheet($sheetname)
-    {
-        $record      = 0x0017;                     // Record identifier
-        $length      = 0x02 + strlen($sheetname);  // Number of bytes to follow
-
-        $cch         = strlen($sheetname);         // Length of sheet name
-        $rgch        = 0x03;                       // Filename encoding
-
-        $header      = pack("vv",  $record, $length);
-        $data        = pack("CC", $cch, $rgch);
-        $this->_append($header . $data . $sheetname);
-    }
-
-
-    /**
-    * Store the NAME record in the short format that is used for storing the print
-    * area, repeat rows only and repeat columns only.
-    *
-    * @param integer $index  Sheet index
-    * @param integer $type   Built-in name type
-    * @param integer $rowmin Start row
-    * @param integer $rowmax End row
-    * @param integer $colmin Start colum
-    * @param integer $colmax End column
-    * @access private
-    */
-    function _storeNameShort($index, $type, $rowmin, $rowmax, $colmin, $colmax)
-    {
-        $record          = 0x0018;       // Record identifier
-        $length          = 0x0024;       // Number of bytes to follow
-
-        $grbit           = 0x0020;       // Option flags
-        $chKey           = 0x00;         // Keyboard shortcut
-        $cch             = 0x01;         // Length of text name
-        $cce             = 0x0015;       // Length of text definition
-        $ixals           = $index + 1;   // Sheet index
-        $itab            = $ixals;       // Equal to ixals
-        $cchCustMenu     = 0x00;         // Length of cust menu text
-        $cchDescription  = 0x00;         // Length of description text
-        $cchHelptopic    = 0x00;         // Length of help topic text
-        $cchStatustext   = 0x00;         // Length of status bar text
-        $rgch            = $type;        // Built-in name type
-
-        $unknown03       = 0x3b;
-        $unknown04       = 0xffff-$index;
-        $unknown05       = 0x0000;
-        $unknown06       = 0x0000;
-        $unknown07       = 0x1087;
-        $unknown08       = 0x8005;
-
-        $header             = pack("vv", $record, $length);
-        $data               = pack("v", $grbit);
-        $data              .= pack("C", $chKey);
-        $data              .= pack("C", $cch);
-        $data              .= pack("v", $cce);
-        $data              .= pack("v", $ixals);
-        $data              .= pack("v", $itab);
-        $data              .= pack("C", $cchCustMenu);
-        $data              .= pack("C", $cchDescription);
-        $data              .= pack("C", $cchHelptopic);
-        $data              .= pack("C", $cchStatustext);
-        $data              .= pack("C", $rgch);
-        $data              .= pack("C", $unknown03);
-        $data              .= pack("v", $unknown04);
-        $data              .= pack("v", $unknown05);
-        $data              .= pack("v", $unknown06);
-        $data              .= pack("v", $unknown07);
-        $data              .= pack("v", $unknown08);
-        $data              .= pack("v", $index);
-        $data              .= pack("v", $index);
-        $data              .= pack("v", $rowmin);
-        $data              .= pack("v", $rowmax);
-        $data              .= pack("C", $colmin);
-        $data              .= pack("C", $colmax);
-        $this->_append($header . $data);
-    }
-
-
-    /**
-    * Store the NAME record in the long format that is used for storing the repeat
-    * rows and columns when both are specified. This shares a lot of code with
-    * _storeNameShort() but we use a separate method to keep the code clean.
-    * Code abstraction for reuse can be carried too far, and I should know. ;-)
-    *
-    * @param integer $index Sheet index
-    * @param integer $type  Built-in name type
-    * @param integer $rowmin Start row
-    * @param integer $rowmax End row
-    * @param integer $colmin Start colum
-    * @param integer $colmax End column
-    * @access private
-    */
-    function _storeNameLong($index, $type, $rowmin, $rowmax, $colmin, $colmax)
-    {
-        $record          = 0x0018;       // Record identifier
-        $length          = 0x003d;       // Number of bytes to follow
-        $grbit           = 0x0020;       // Option flags
-        $chKey           = 0x00;         // Keyboard shortcut
-        $cch             = 0x01;         // Length of text name
-        $cce             = 0x002e;       // Length of text definition
-        $ixals           = $index + 1;   // Sheet index
-        $itab            = $ixals;       // Equal to ixals
-        $cchCustMenu     = 0x00;         // Length of cust menu text
-        $cchDescription  = 0x00;         // Length of description text
-        $cchHelptopic    = 0x00;         // Length of help topic text
-        $cchStatustext   = 0x00;         // Length of status bar text
-        $rgch            = $type;        // Built-in name type
-
-        $unknown01       = 0x29;
-        $unknown02       = 0x002b;
-        $unknown03       = 0x3b;
-        $unknown04       = 0xffff-$index;
-        $unknown05       = 0x0000;
-        $unknown06       = 0x0000;
-        $unknown07       = 0x1087;
-        $unknown08       = 0x8008;
-
-        $header             = pack("vv",  $record, $length);
-        $data               = pack("v", $grbit);
-        $data              .= pack("C", $chKey);
-        $data              .= pack("C", $cch);
-        $data              .= pack("v", $cce);
-        $data              .= pack("v", $ixals);
-        $data              .= pack("v", $itab);
-        $data              .= pack("C", $cchCustMenu);
-        $data              .= pack("C", $cchDescription);
-        $data              .= pack("C", $cchHelptopic);
-        $data              .= pack("C", $cchStatustext);
-        $data              .= pack("C", $rgch);
-        $data              .= pack("C", $unknown01);
-        $data              .= pack("v", $unknown02);
-        // Column definition
-        $data              .= pack("C", $unknown03);
-        $data              .= pack("v", $unknown04);
-        $data              .= pack("v", $unknown05);
-        $data              .= pack("v", $unknown06);
-        $data              .= pack("v", $unknown07);
-        $data              .= pack("v", $unknown08);
-        $data              .= pack("v", $index);
-        $data              .= pack("v", $index);
-        $data              .= pack("v", 0x0000);
-        $data              .= pack("v", 0x3fff);
-        $data              .= pack("C", $colmin);
-        $data              .= pack("C", $colmax);
-        // Row definition
-        $data              .= pack("C", $unknown03);
-        $data              .= pack("v", $unknown04);
-        $data              .= pack("v", $unknown05);
-        $data              .= pack("v", $unknown06);
-        $data              .= pack("v", $unknown07);
-        $data              .= pack("v", $unknown08);
-        $data              .= pack("v", $index);
-        $data              .= pack("v", $index);
-        $data              .= pack("v", $rowmin);
-        $data              .= pack("v", $rowmax);
-        $data              .= pack("C", 0x00);
-        $data              .= pack("C", 0xff);
-        // End of data
-        $data              .= pack("C", 0x10);
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Stores the COUNTRY record for localization
-    *
-    * @access private
-    */
-    function _storeCountry()
-    {
-        $record          = 0x008C;    // Record identifier
-        $length          = 4;         // Number of bytes to follow
-
-        $header = pack('vv',  $record, $length);
-        /* using the same country code always for simplicity */
-        $data = pack('vv', $this->_country_code, $this->_country_code);
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Stores the PALETTE biff record.
-    *
-    * @access private
-    */
-    function _storePalette()
-    {
-        $aref            = $this->_palette;
-
-        $record          = 0x0092;                 // Record identifier
-        $length          = 2 + 4 * count($aref);   // Number of bytes to follow
-        $ccv             =         count($aref);   // Number of RGB values to follow
-        $data = '';                                // The RGB data
-
-        // Pack the RGB data
-        foreach ($aref as $color) {
-            foreach ($color as $byte) {
-                $data .= pack("C",$byte);
-            }
-        }
-
-        $header = pack("vvv",  $record, $length, $ccv);
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Calculate
-    * Handling of the SST continue blocks is complicated by the need to include an
-    * additional continuation byte depending on whether the string is split between
-    * blocks or whether it starts at the beginning of the block. (There are also
-    * additional complications that will arise later when/if Rich Strings are
-    * supported).
-    *
-    * @access private
-    */
-    function _calculateSharedStringsSizes()
-    {
-        /* Iterate through the strings to calculate the CONTINUE block sizes.
-           For simplicity we use the same size for the SST and CONTINUE records:
-           8228 : Maximum Excel97 block size
-             -4 : Length of block header
-             -8 : Length of additional SST header information
-             -8 : Arbitrary number to keep within _add_continue() limit = 8208
-        */
-        $continue_limit     = 8208;
-        $block_length       = 0;
-        $written            = 0;
-        $this->_block_sizes = array();
-        $continue           = 0;
-
-        foreach (array_keys($this->_str_table) as $string) {
-            $string_length = strlen($string);
-            $headerinfo    = unpack("vlength/Cencoding", $string);
-            $encoding      = $headerinfo["encoding"];
-            $split_string  = 0;
-
-            // Block length is the total length of the strings that will be
-            // written out in a single SST or CONTINUE block.
-            $block_length += $string_length;
-
-            // We can write the string if it doesn't cross a CONTINUE boundary
-            if ($block_length < $continue_limit) {
-                $written      += $string_length;
-                continue;
-            }
-
-            // Deal with the cases where the next string to be written will exceed
-            // the CONTINUE boundary. If the string is very long it may need to be
-            // written in more than one CONTINUE record.
-            while ($block_length >= $continue_limit) {
-
-                // We need to avoid the case where a string is continued in the first
-                // n bytes that contain the string header information.
-                $header_length   = 3; // Min string + header size -1
-                $space_remaining = $continue_limit - $written - $continue;
-
-
-                /* TODO: Unicode data should only be split on char (2 byte)
-                boundaries. Therefore, in some cases we need to reduce the
-                amount of available
-                */
-                $align = 0;
-
-                // Only applies to Unicode strings
-                if ($encoding == 1) {
-                    // Min string + header size -1
-                    $header_length = 4;
-
-                    if ($space_remaining > $header_length) {
-                        // String contains 3 byte header => split on odd boundary
-                        if (!$split_string && $space_remaining % 2 != 1) {
-                            $space_remaining--;
-                            $align = 1;
-                        }
-                        // Split section without header => split on even boundary
-                        else if ($split_string && $space_remaining % 2 == 1) {
-                            $space_remaining--;
-                            $align = 1;
-                        }
-
-                        $split_string = 1;
-                    }
-                }
-
-
-                if ($space_remaining > $header_length) {
-                    // Write as much as possible of the string in the current block
-                    $written      += $space_remaining;
-
-                    // Reduce the current block length by the amount written
-                    $block_length -= $continue_limit - $continue - $align;
-
-                    // Store the max size for this block
-                    $this->_block_sizes[] = $continue_limit - $align;
-
-                    // If the current string was split then the next CONTINUE block
-                    // should have the string continue flag (grbit) set unless the
-                    // split string fits exactly into the remaining space.
-                    if ($block_length > 0) {
-                        $continue = 1;
-                    } else {
-                        $continue = 0;
-                    }
-                } else {
-                    // Store the max size for this block
-                    $this->_block_sizes[] = $written + $continue;
-
-                    // Not enough space to start the string in the current block
-                    $block_length -= $continue_limit - $space_remaining - $continue;
-                    $continue = 0;
-
-                }
-
-                // If the string (or substr) is small enough we can write it in the
-                // new CONTINUE block. Else, go through the loop again to write it in
-                // one or more CONTINUE blocks
-                if ($block_length < $continue_limit) {
-                    $written = $block_length;
-                } else {
-                    $written = 0;
-                }
-            }
-        }
-
-        // Store the max size for the last block unless it is empty
-        if ($written + $continue) {
-            $this->_block_sizes[] = $written + $continue;
-        }
-
-
-        /* Calculate the total length of the SST and associated CONTINUEs (if any).
-         The SST record will have a length even if it contains no strings.
-         This length is required to set the offsets in the BOUNDSHEET records since
-         they must be written before the SST records
-        */
-
-        $tmp_block_sizes = array();
-        $tmp_block_sizes = $this->_block_sizes;
-
-        $length  = 12;
-        if (!empty($tmp_block_sizes)) {
-            $length += array_shift($tmp_block_sizes); // SST
-        }
-        while (!empty($tmp_block_sizes)) {
-            $length += 4 + array_shift($tmp_block_sizes); // CONTINUEs
-        }
-
-        return $length;
-    }
-
-    /**
-    * Write all of the workbooks strings into an indexed array.
-    * See the comments in _calculate_shared_string_sizes() for more information.
-    *
-    * The Excel documentation says that the SST record should be followed by an
-    * EXTSST record. The EXTSST record is a hash table that is used to optimise
-    * access to SST. However, despite the documentation it doesn't seem to be
-    * required so we will ignore it.
-    *
-    * @access private
-    */
-    function _storeSharedStringsTable()
-    {
-        $record  = 0x00fc;  // Record identifier
-        $length  = 0x0008;  // Number of bytes to follow
-        $total   = 0x0000;
-
-        // Iterate through the strings to calculate the CONTINUE block sizes
-        $continue_limit = 8208;
-        $block_length   = 0;
-        $written        = 0;
-        $continue       = 0;
-
-        // sizes are upside down
-        $tmp_block_sizes = $this->_block_sizes;
-        // $tmp_block_sizes = array_reverse($this->_block_sizes);
-
-        // The SST record is required even if it contains no strings. Thus we will
-        // always have a length
-        //
-        if (!empty($tmp_block_sizes)) {
-            $length = 8 + array_shift($tmp_block_sizes);
-        }
-        else {
-            // No strings
-            $length = 8;
-        }
-
-
-
-        // Write the SST block header information
-        $header      = pack("vv", $record, $length);
-        $data        = pack("VV", $this->_str_total, $this->_str_unique);
-        $this->_append($header . $data);
-
-
-
-
-        /* TODO: not good for performance */
-        foreach (array_keys($this->_str_table) as $string) {
-
-            $string_length = strlen($string);
-            $headerinfo    = unpack("vlength/Cencoding", $string);
-            $encoding      = $headerinfo["encoding"];
-            $split_string  = 0;
-
-            // Block length is the total length of the strings that will be
-            // written out in a single SST or CONTINUE block.
-            //
-            $block_length += $string_length;
-
-
-            // We can write the string if it doesn't cross a CONTINUE boundary
-            if ($block_length < $continue_limit) {
-                $this->_append($string);
-                $written += $string_length;
-                continue;
-            }
-
-            // Deal with the cases where the next string to be written will exceed
-            // the CONTINUE boundary. If the string is very long it may need to be
-            // written in more than one CONTINUE record.
-            //
-            while ($block_length >= $continue_limit) {
-
-                // We need to avoid the case where a string is continued in the first
-                // n bytes that contain the string header information.
-                //
-                $header_length   = 3; // Min string + header size -1
-                $space_remaining = $continue_limit - $written - $continue;
-
-
-                // Unicode data should only be split on char (2 byte) boundaries.
-                // Therefore, in some cases we need to reduce the amount of available
-                // space by 1 byte to ensure the correct alignment.
-                $align = 0;
-
-                // Only applies to Unicode strings
-                if ($encoding == 1) {
-                    // Min string + header size -1
-                    $header_length = 4;
-
-                    if ($space_remaining > $header_length) {
-                        // String contains 3 byte header => split on odd boundary
-                        if (!$split_string && $space_remaining % 2 != 1) {
-                            $space_remaining--;
-                            $align = 1;
-                        }
-                        // Split section without header => split on even boundary
-                        else if ($split_string && $space_remaining % 2 == 1) {
-                            $space_remaining--;
-                            $align = 1;
-                        }
-
-                        $split_string = 1;
-                    }
-                }
-
-
-                if ($space_remaining > $header_length) {
-                    // Write as much as possible of the string in the current block
-                    $tmp = substr($string, 0, $space_remaining);
-                    $this->_append($tmp);
-
-                    // The remainder will be written in the next block(s)
-                    $string = substr($string, $space_remaining);
-
-                    // Reduce the current block length by the amount written
-                    $block_length -= $continue_limit - $continue - $align;
-
-                    // If the current string was split then the next CONTINUE block
-                    // should have the string continue flag (grbit) set unless the
-                    // split string fits exactly into the remaining space.
-                    //
-                    if ($block_length > 0) {
-                        $continue = 1;
-                    } else {
-                        $continue = 0;
-                    }
-                } else {
-                    // Not enough space to start the string in the current block
-                    $block_length -= $continue_limit - $space_remaining - $continue;
-                    $continue = 0;
-                }
-
-                // Write the CONTINUE block header
-                if (!empty($this->_block_sizes)) {
-                    $record  = 0x003C;
-                    $length  = array_shift($tmp_block_sizes);
-
-                    $header  = pack('vv', $record, $length);
-                    if ($continue) {
-                        $header .= pack('C', $encoding);
-                    }
-                    $this->_append($header);
-                }
-
-                // If the string (or substr) is small enough we can write it in the
-                // new CONTINUE block. Else, go through the loop again to write it in
-                // one or more CONTINUE blocks
-                //
-                if ($block_length < $continue_limit) {
-                    $this->_append($string);
-                    $written = $block_length;
-                } else {
-                    $written = 0;
-                }
-            }
-        }
-    }
-
-
-}
-

+ 0 - 3534
main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/Worksheet.php

@@ -1,3534 +0,0 @@
-<?php
-/*
-*  Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
-*
-*  The majority of this is _NOT_ my code.  I simply ported it from the
-*  PERL Spreadsheet::WriteExcel module.
-*
-*  The author of the Spreadsheet::WriteExcel module is John McNamara
-*  <jmcnamara@cpan.org>
-*
-*  I _DO_ maintain this code, and John McNamara has nothing to do with the
-*  porting of this code to PHP.  Any questions directly related to this
-*  class library should be directed to me.
-*
-*  License Information:
-*
-*    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
-*    Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
-*
-*    This library is free software; you can redistribute it and/or
-*    modify it under the terms of the GNU Lesser General Public
-*    License as published by the Free Software Foundation; either
-*    version 2.1 of the License, or (at your option) any later version.
-*
-*    This library is distributed in the hope that it will be useful,
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-*    Lesser General Public License for more details.
-*
-*    You should have received a copy of the GNU Lesser General Public
-*    License along with this library; if not, write to the Free Software
-*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer/Parser.php';
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer/BIFFwriter.php';
-
-/**
-* Class for generating Excel Spreadsheets
-*
-* @author   Xavier Noguer <xnoguer@rezebra.com>
-* @category FileFormats
-* @package  Spreadsheet_Excel_Writer
-*/
-
-class Spreadsheet_Excel_Writer_Worksheet extends Spreadsheet_Excel_Writer_BIFFwriter
-{
-    /**
-    * Name of the Worksheet
-    * @var string
-    */
-    var $name;
-
-    /**
-    * Index for the Worksheet
-    * @var integer
-    */
-    var $index;
-
-    /**
-    * Reference to the (default) Format object for URLs
-    * @var object Format
-    */
-    var $_url_format;
-
-    /**
-    * Reference to the parser used for parsing formulas
-    * @var object Format
-    */
-    var $_parser;
-
-    /**
-    * Filehandle to the temporary file for storing data
-    * @var resource
-    */
-    var $_filehandle;
-
-    /**
-    * Boolean indicating if we are using a temporary file for storing data
-    * @var bool
-    */
-    var $_using_tmpfile;
-
-    /**
-    * Maximum number of rows for an Excel spreadsheet (BIFF5)
-    * @var integer
-    */
-    var $_xls_rowmax;
-
-    /**
-    * Maximum number of columns for an Excel spreadsheet (BIFF5)
-    * @var integer
-    */
-    var $_xls_colmax;
-
-    /**
-    * Maximum number of characters for a string (LABEL record in BIFF5)
-    * @var integer
-    */
-    var $_xls_strmax;
-
-    /**
-    * First row for the DIMENSIONS record
-    * @var integer
-    * @see _storeDimensions()
-    */
-    var $_dim_rowmin;
-
-    /**
-    * Last row for the DIMENSIONS record
-    * @var integer
-    * @see _storeDimensions()
-    */
-    var $_dim_rowmax;
-
-    /**
-    * First column for the DIMENSIONS record
-    * @var integer
-    * @see _storeDimensions()
-    */
-    var $_dim_colmin;
-
-    /**
-    * Last column for the DIMENSIONS record
-    * @var integer
-    * @see _storeDimensions()
-    */
-    var $_dim_colmax;
-
-    /**
-    * Array containing format information for columns
-    * @var array
-    */
-    var $_colinfo;
-
-    /**
-    * Array containing the selected area for the worksheet
-    * @var array
-    */
-    var $_selection;
-
-    /**
-    * Array containing the panes for the worksheet
-    * @var array
-    */
-    var $_panes;
-
-    /**
-    * The active pane for the worksheet
-    * @var integer
-    */
-    var $_active_pane;
-
-    /**
-    * Bit specifying if panes are frozen
-    * @var integer
-    */
-    var $_frozen;
-
-    /**
-    * Bit specifying if the worksheet is selected
-    * @var integer
-    */
-    var $selected;
-
-    /**
-    * The paper size (for printing) (DOCUMENT!!!)
-    * @var integer
-    */
-    var $_paper_size;
-
-    /**
-    * Bit specifying paper orientation (for printing). 0 => landscape, 1 => portrait
-    * @var integer
-    */
-    var $_orientation;
-
-    /**
-    * The page header caption
-    * @var string
-    */
-    var $_header;
-
-    /**
-    * The page footer caption
-    * @var string
-    */
-    var $_footer;
-
-    /**
-    * The horizontal centering value for the page
-    * @var integer
-    */
-    var $_hcenter;
-
-    /**
-    * The vertical centering value for the page
-    * @var integer
-    */
-    var $_vcenter;
-
-    /**
-    * The margin for the header
-    * @var float
-    */
-    var $_margin_head;
-
-    /**
-    * The margin for the footer
-    * @var float
-    */
-    var $_margin_foot;
-
-    /**
-    * The left margin for the worksheet in inches
-    * @var float
-    */
-    var $_margin_left;
-
-    /**
-    * The right margin for the worksheet in inches
-    * @var float
-    */
-    var $_margin_right;
-
-    /**
-    * The top margin for the worksheet in inches
-    * @var float
-    */
-    var $_margin_top;
-
-    /**
-    * The bottom margin for the worksheet in inches
-    * @var float
-    */
-    var $_margin_bottom;
-
-    /**
-    * First row to reapeat on each printed page
-    * @var integer
-    */
-    var $title_rowmin;
-
-    /**
-    * Last row to reapeat on each printed page
-    * @var integer
-    */
-    var $title_rowmax;
-
-    /**
-    * First column to reapeat on each printed page
-    * @var integer
-    */
-    var $title_colmin;
-
-    /**
-    * First row of the area to print
-    * @var integer
-    */
-    var $print_rowmin;
-
-    /**
-    * Last row to of the area to print
-    * @var integer
-    */
-    var $print_rowmax;
-
-    /**
-    * First column of the area to print
-    * @var integer
-    */
-    var $print_colmin;
-
-    /**
-    * Last column of the area to print
-    * @var integer
-    */
-    var $print_colmax;
-
-    /**
-    * Whether to use outline.
-    * @var integer
-    */
-    var $_outline_on;
-
-    /**
-    * Auto outline styles.
-    * @var bool
-    */
-    var $_outline_style;
-
-    /**
-    * Whether to have outline summary below.
-    * @var bool
-    */
-    var $_outline_below;
-
-    /**
-    * Whether to have outline summary at the right.
-    * @var bool
-    */
-    var $_outline_right;
-
-    /**
-    * Outline row level.
-    * @var integer
-    */
-    var $_outline_row_level;
-
-    /**
-    * Whether to fit to page when printing or not.
-    * @var bool
-    */
-    var $_fit_page;
-
-    /**
-    * Number of pages to fit wide
-    * @var integer
-    */
-    var $_fit_width;
-
-    /**
-    * Number of pages to fit high
-    * @var integer
-    */
-    var $_fit_height;
-
-    /**
-    * Reference to the total number of strings in the workbook
-    * @var integer
-    */
-    var $_str_total;
-
-    /**
-    * Reference to the number of unique strings in the workbook
-    * @var integer
-    */
-    var $_str_unique;
-
-    /**
-    * Reference to the array containing all the unique strings in the workbook
-    * @var array
-    */
-    var $_str_table;
-
-    /**
-    * Merged cell ranges
-    * @var array
-    */
-    var $_merged_ranges;
-
-    /**
-    * Charset encoding currently used when calling writeString()
-    * @var string
-    */
-    var $_input_encoding;
-
-    /**
-    * Constructor
-    *
-    * @param string  $name         The name of the new worksheet
-    * @param integer $index        The index of the new worksheet
-    * @param mixed   &$activesheet The current activesheet of the workbook we belong to
-    * @param mixed   &$firstsheet  The first worksheet in the workbook we belong to
-    * @param mixed   &$url_format  The default format for hyperlinks
-    * @param mixed   &$parser      The formula parser created for the Workbook
-    * @param string  $tmp_dir      The path to the directory for temporary files
-    * @access private
-    */
-    function Spreadsheet_Excel_Writer_Worksheet($BIFF_version, $name,
-                                                $index, &$activesheet,
-                                                &$firstsheet, &$str_total,
-                                                &$str_unique, &$str_table,
-                                                &$url_format, &$parser,
-                                                $tmp_dir)
-    {
-        // It needs to call its parent's constructor explicitly
-        $this->Spreadsheet_Excel_Writer_BIFFwriter();
-        $this->_BIFF_version   = $BIFF_version;
-        $rowmax                = 65536; // 16384 in Excel 5
-        $colmax                = 256;
-
-        $this->name            = $name;
-        $this->index           = $index;
-        $this->activesheet     = &$activesheet;
-        $this->firstsheet      = &$firstsheet;
-        $this->_str_total      = &$str_total;
-        $this->_str_unique     = &$str_unique;
-        $this->_str_table      = &$str_table;
-        $this->_url_format     = &$url_format;
-        $this->_parser         = &$parser;
-
-        //$this->ext_sheets      = array();
-        $this->_filehandle     = '';
-        $this->_using_tmpfile  = true;
-        //$this->fileclosed      = 0;
-        //$this->offset          = 0;
-        $this->_xls_rowmax     = $rowmax;
-        $this->_xls_colmax     = $colmax;
-        $this->_xls_strmax     = 255;
-        $this->_dim_rowmin     = $rowmax + 1;
-        $this->_dim_rowmax     = 0;
-        $this->_dim_colmin     = $colmax + 1;
-        $this->_dim_colmax     = 0;
-        $this->_colinfo        = array();
-        $this->_selection      = array(0,0,0,0);
-        $this->_panes          = array();
-        $this->_active_pane    = 3;
-        $this->_frozen         = 0;
-        $this->selected        = 0;
-
-        $this->_paper_size      = 0x0;
-        $this->_orientation     = 0x1;
-        $this->_header          = '';
-        $this->_footer          = '';
-        $this->_hcenter         = 0;
-        $this->_vcenter         = 0;
-        $this->_margin_head     = 0.50;
-        $this->_margin_foot     = 0.50;
-        $this->_margin_left     = 0.75;
-        $this->_margin_right    = 0.75;
-        $this->_margin_top      = 1.00;
-        $this->_margin_bottom   = 1.00;
-
-        $this->title_rowmin     = null;
-        $this->title_rowmax     = null;
-        $this->title_colmin     = null;
-        $this->title_colmax     = null;
-        $this->print_rowmin     = null;
-        $this->print_rowmax     = null;
-        $this->print_colmin     = null;
-        $this->print_colmax     = null;
-
-        $this->_print_gridlines  = 1;
-        $this->_screen_gridlines = 1;
-        $this->_print_headers    = 0;
-
-        $this->_fit_page        = 0;
-        $this->_fit_width       = 0;
-        $this->_fit_height      = 0;
-
-        $this->_hbreaks         = array();
-        $this->_vbreaks         = array();
-
-        $this->_protect         = 0;
-        $this->_password        = null;
-
-        $this->col_sizes        = array();
-        $this->_row_sizes        = array();
-
-        $this->_zoom            = 100;
-        $this->_print_scale     = 100;
-
-        $this->_outline_row_level = 0;
-        $this->_outline_style     = 0;
-        $this->_outline_below     = 1;
-        $this->_outline_right     = 1;
-        $this->_outline_on        = 1;
-
-        $this->_merged_ranges     = array();
-
-        $this->_input_encoding    = '';
-
-        $this->_dv                = array();
-
-        $this->_tmp_dir = $tmp_dir;
-
-        $this->_initialize();
-    }
-
-    /**
-    * Open a tmp file to store the majority of the Worksheet data. If this fails,
-    * for example due to write permissions, store the data in memory. This can be
-    * slow for large files.
-    *
-    * @access private
-    */
-    function _initialize()
-    {
-        if ($this->_using_tmpfile == false) {
-            return;
-        }
-
-        if ($this->_tmp_dir === '' && ini_get('open_basedir') === false) {
-            // open_basedir restriction in effect - store data in memory
-            // ToDo: Let the error actually have an effect somewhere
-            $this->_using_tmpfile = false;
-            return new PEAR_Error('Temp file could not be opened since open_basedir restriction in effect - please use setTmpDir() - using memory storage instead');
-        }
-
-        // Open tmp file for storing Worksheet data
-        if ($this->_tmp_dir === '') {
-            $fh = tmpfile();
-        } else {
-            // For people with open base dir restriction
-            $tmpfilename = tempnam($this->_tmp_dir, "Spreadsheet_Excel_Writer");
-            $fh = @fopen($tmpfilename, "w+b");
-        }
-
-        if ($fh === false) {
-            // If tmpfile() fails store data in memory
-            $this->_using_tmpfile = false;
-        } else {
-            // Store filehandle
-            $this->_filehandle = $fh;
-        }
-    }
-
-    /**
-    * Add data to the beginning of the workbook (note the reverse order)
-    * and to the end of the workbook.
-    *
-    * @access public
-    * @see Spreadsheet_Excel_Writer_Workbook::storeWorkbook()
-    * @param array $sheetnames The array of sheetnames from the Workbook this
-    *                          worksheet belongs to
-    */
-    function close($sheetnames)
-    {
-        $num_sheets = count($sheetnames);
-
-        /***********************************************
-        * Prepend in reverse order!!
-        */
-
-        // Prepend the sheet dimensions
-        $this->_storeDimensions();
-
-        // Prepend the sheet password
-        $this->_storePassword();
-
-        // Prepend the sheet protection
-        $this->_storeProtect();
-
-        // Prepend the page setup
-        $this->_storeSetup();
-
-        /* FIXME: margins are actually appended */
-        // Prepend the bottom margin
-        $this->_storeMarginBottom();
-
-        // Prepend the top margin
-        $this->_storeMarginTop();
-
-        // Prepend the right margin
-        $this->_storeMarginRight();
-
-        // Prepend the left margin
-        $this->_storeMarginLeft();
-
-        // Prepend the page vertical centering
-        $this->_storeVcenter();
-
-        // Prepend the page horizontal centering
-        $this->_storeHcenter();
-
-        // Prepend the page footer
-        $this->_storeFooter();
-
-        // Prepend the page header
-        $this->_storeHeader();
-
-        // Prepend the vertical page breaks
-        $this->_storeVbreak();
-
-        // Prepend the horizontal page breaks
-        $this->_storeHbreak();
-
-        // Prepend WSBOOL
-        $this->_storeWsbool();
-
-        // Prepend GRIDSET
-        $this->_storeGridset();
-
-         //  Prepend GUTS
-        if ($this->_BIFF_version == 0x0500) {
-            $this->_storeGuts();
-        }
-
-        // Prepend PRINTGRIDLINES
-        $this->_storePrintGridlines();
-
-        // Prepend PRINTHEADERS
-        $this->_storePrintHeaders();
-
-        // Prepend EXTERNSHEET references
-        if ($this->_BIFF_version == 0x0500) {
-            for ($i = $num_sheets; $i > 0; $i--) {
-                $sheetname = $sheetnames[$i-1];
-                $this->_storeExternsheet($sheetname);
-            }
-        }
-
-        // Prepend the EXTERNCOUNT of external references.
-        if ($this->_BIFF_version == 0x0500) {
-            $this->_storeExterncount($num_sheets);
-        }
-
-        // Prepend the COLINFO records if they exist
-        if (!empty($this->_colinfo)) {
-            $colcount = count($this->_colinfo);
-            for ($i = 0; $i < $colcount; $i++) {
-                $this->_storeColinfo($this->_colinfo[$i]);
-            }
-            $this->_storeDefcol();
-        }
-
-        // Prepend the BOF record
-        $this->_storeBof(0x0010);
-
-        /*
-        * End of prepend. Read upwards from here.
-        ***********************************************/
-
-        // Append
-        $this->_storeWindow2();
-        $this->_storeZoom();
-        if (!empty($this->_panes)) {
-            $this->_storePanes($this->_panes);
-        }
-        $this->_storeSelection($this->_selection);
-        $this->_storeMergedCells();
-        /* TODO: add data validity */
-        /*if ($this->_BIFF_version == 0x0600) {
-            $this->_storeDataValidity();
-        }*/
-        $this->_storeEof();
-    }
-
-    /**
-    * Retrieve the worksheet name.
-    * This is usefull when creating worksheets without a name.
-    *
-    * @access public
-    * @return string The worksheet's name
-    */
-    function getName()
-    {
-        return $this->name;
-    }
-
-    /**
-    * Retrieves data from memory in one chunk, or from disk in $buffer
-    * sized chunks.
-    *
-    * @return string The data
-    */
-    function getData()
-    {
-        $buffer = 4096;
-
-        // Return data stored in memory
-        if (isset($this->_data)) {
-            $tmp   = $this->_data;
-            unset($this->_data);
-            $fh    = $this->_filehandle;
-            if ($this->_using_tmpfile) {
-                fseek($fh, 0);
-            }
-            return $tmp;
-        }
-        // Return data stored on disk
-        if ($this->_using_tmpfile) {
-            if ($tmp = fread($this->_filehandle, $buffer)) {
-                return $tmp;
-            }
-        }
-
-        // No data to return
-        return '';
-    }
-
-    /**
-    * Sets a merged cell range
-    *
-    * @access public
-    * @param integer $first_row First row of the area to merge
-    * @param integer $first_col First column of the area to merge
-    * @param integer $last_row  Last row of the area to merge
-    * @param integer $last_col  Last column of the area to merge
-    */
-    function setMerge($first_row, $first_col, $last_row, $last_col)
-    {
-        if (($last_row < $first_row) || ($last_col < $first_col)) {
-            return;
-        }
-        // don't check rowmin, rowmax, etc... because we don't know when this
-        // is going to be called
-        $this->_merged_ranges[] = array($first_row, $first_col, $last_row, $last_col);
-    }
-
-    /**
-    * Set this worksheet as a selected worksheet,
-    * i.e. the worksheet has its tab highlighted.
-    *
-    * @access public
-    */
-    function select()
-    {
-        $this->selected = 1;
-    }
-
-    /**
-    * Set this worksheet as the active worksheet,
-    * i.e. the worksheet that is displayed when the workbook is opened.
-    * Also set it as selected.
-    *
-    * @access public
-    */
-    function activate()
-    {
-        $this->selected = 1;
-        $this->activesheet = $this->index;
-    }
-
-    /**
-    * Set this worksheet as the first visible sheet.
-    * This is necessary when there are a large number of worksheets and the
-    * activated worksheet is not visible on the screen.
-    *
-    * @access public
-    */
-    function setFirstSheet()
-    {
-        $this->firstsheet = $this->index;
-    }
-
-    /**
-    * Set the worksheet protection flag
-    * to prevent accidental modification and to
-    * hide formulas if the locked and hidden format properties have been set.
-    *
-    * @access public
-    * @param string $password The password to use for protecting the sheet.
-    */
-    function protect($password)
-    {
-        $this->_protect   = 1;
-        $this->_password  = $this->_encodePassword($password);
-    }
-
-    /**
-    * Set the width of a single column or a range of columns.
-    *
-    * @access public
-    * @param integer $firstcol first column on the range
-    * @param integer $lastcol  last column on the range
-    * @param integer $width    width to set
-    * @param mixed   $format   The optional XF format to apply to the columns
-    * @param integer $hidden   The optional hidden atribute
-    * @param integer $level    The optional outline level
-    */
-    function setColumn($firstcol, $lastcol, $width, $format = null, $hidden = 0, $level = 0)
-    {
-        $this->_colinfo[] = array($firstcol, $lastcol, $width, &$format, $hidden, $level);
-
-        // Set width to zero if column is hidden
-        $width = ($hidden) ? 0 : $width;
-
-        for ($col = $firstcol; $col <= $lastcol; $col++) {
-            $this->col_sizes[$col] = $width;
-        }
-    }
-
-    /**
-    * Set which cell or cells are selected in a worksheet
-    *
-    * @access public
-    * @param integer $first_row    first row in the selected quadrant
-    * @param integer $first_column first column in the selected quadrant
-    * @param integer $last_row     last row in the selected quadrant
-    * @param integer $last_column  last column in the selected quadrant
-    */
-    function setSelection($first_row,$first_column,$last_row,$last_column)
-    {
-        $this->_selection = array($first_row,$first_column,$last_row,$last_column);
-    }
-
-    /**
-    * Set panes and mark them as frozen.
-    *
-    * @access public
-    * @param array $panes This is the only parameter received and is composed of the following:
-    *                     0 => Vertical split position,
-    *                     1 => Horizontal split position
-    *                     2 => Top row visible
-    *                     3 => Leftmost column visible
-    *                     4 => Active pane
-    */
-    function freezePanes($panes)
-    {
-        $this->_frozen = 1;
-        $this->_panes  = $panes;
-    }
-
-    /**
-    * Set panes and mark them as unfrozen.
-    *
-    * @access public
-    * @param array $panes This is the only parameter received and is composed of the following:
-    *                     0 => Vertical split position,
-    *                     1 => Horizontal split position
-    *                     2 => Top row visible
-    *                     3 => Leftmost column visible
-    *                     4 => Active pane
-    */
-    function thawPanes($panes)
-    {
-        $this->_frozen = 0;
-        $this->_panes  = $panes;
-    }
-
-    /**
-    * Set the page orientation as portrait.
-    *
-    * @access public
-    */
-    function setPortrait()
-    {
-        $this->_orientation = 1;
-    }
-
-    /**
-    * Set the page orientation as landscape.
-    *
-    * @access public
-    */
-    function setLandscape()
-    {
-        $this->_orientation = 0;
-    }
-
-    /**
-    * Set the paper type. Ex. 1 = US Letter, 9 = A4
-    *
-    * @access public
-    * @param integer $size The type of paper size to use
-    */
-    function setPaper($size = 0)
-    {
-        $this->_paper_size = $size;
-    }
-
-
-    /**
-    * Set the page header caption and optional margin.
-    *
-    * @access public
-    * @param string $string The header text
-    * @param float  $margin optional head margin in inches.
-    */
-    function setHeader($string,$margin = 0.50)
-    {
-        if (strlen($string) >= 255) {
-            //carp 'Header string must be less than 255 characters';
-            return;
-        }
-        $this->_header      = $string;
-        $this->_margin_head = $margin;
-    }
-
-    /**
-    * Set the page footer caption and optional margin.
-    *
-    * @access public
-    * @param string $string The footer text
-    * @param float  $margin optional foot margin in inches.
-    */
-    function setFooter($string,$margin = 0.50)
-    {
-        if (strlen($string) >= 255) {
-            //carp 'Footer string must be less than 255 characters';
-            return;
-        }
-        $this->_footer      = $string;
-        $this->_margin_foot = $margin;
-    }
-
-    /**
-    * Center the page horinzontally.
-    *
-    * @access public
-    * @param integer $center the optional value for centering. Defaults to 1 (center).
-    */
-    function centerHorizontally($center = 1)
-    {
-        $this->_hcenter = $center;
-    }
-
-    /**
-    * Center the page vertically.
-    *
-    * @access public
-    * @param integer $center the optional value for centering. Defaults to 1 (center).
-    */
-    function centerVertically($center = 1)
-    {
-        $this->_vcenter = $center;
-    }
-
-    /**
-    * Set all the page margins to the same value in inches.
-    *
-    * @access public
-    * @param float $margin The margin to set in inches
-    */
-    function setMargins($margin)
-    {
-        $this->setMarginLeft($margin);
-        $this->setMarginRight($margin);
-        $this->setMarginTop($margin);
-        $this->setMarginBottom($margin);
-    }
-
-    /**
-    * Set the left and right margins to the same value in inches.
-    *
-    * @access public
-    * @param float $margin The margin to set in inches
-    */
-    function setMargins_LR($margin)
-    {
-        $this->setMarginLeft($margin);
-        $this->setMarginRight($margin);
-    }
-
-    /**
-    * Set the top and bottom margins to the same value in inches.
-    *
-    * @access public
-    * @param float $margin The margin to set in inches
-    */
-    function setMargins_TB($margin)
-    {
-        $this->setMarginTop($margin);
-        $this->setMarginBottom($margin);
-    }
-
-    /**
-    * Set the left margin in inches.
-    *
-    * @access public
-    * @param float $margin The margin to set in inches
-    */
-    function setMarginLeft($margin = 0.75)
-    {
-        $this->_margin_left = $margin;
-    }
-
-    /**
-    * Set the right margin in inches.
-    *
-    * @access public
-    * @param float $margin The margin to set in inches
-    */
-    function setMarginRight($margin = 0.75)
-    {
-        $this->_margin_right = $margin;
-    }
-
-    /**
-    * Set the top margin in inches.
-    *
-    * @access public
-    * @param float $margin The margin to set in inches
-    */
-    function setMarginTop($margin = 1.00)
-    {
-        $this->_margin_top = $margin;
-    }
-
-    /**
-    * Set the bottom margin in inches.
-    *
-    * @access public
-    * @param float $margin The margin to set in inches
-    */
-    function setMarginBottom($margin = 1.00)
-    {
-        $this->_margin_bottom = $margin;
-    }
-
-    /**
-    * Set the rows to repeat at the top of each printed page.
-    *
-    * @access public
-    * @param integer $first_row First row to repeat
-    * @param integer $last_row  Last row to repeat. Optional.
-    */
-    function repeatRows($first_row, $last_row = null)
-    {
-        $this->title_rowmin  = $first_row;
-        if (isset($last_row)) { //Second row is optional
-            $this->title_rowmax  = $last_row;
-        } else {
-            $this->title_rowmax  = $first_row;
-        }
-    }
-
-    /**
-    * Set the columns to repeat at the left hand side of each printed page.
-    *
-    * @access public
-    * @param integer $first_col First column to repeat
-    * @param integer $last_col  Last column to repeat. Optional.
-    */
-    function repeatColumns($first_col, $last_col = null)
-    {
-        $this->title_colmin  = $first_col;
-        if (isset($last_col)) { // Second col is optional
-            $this->title_colmax  = $last_col;
-        } else {
-            $this->title_colmax  = $first_col;
-        }
-    }
-
-    /**
-    * Set the area of each worksheet that will be printed.
-    *
-    * @access public
-    * @param integer $first_row First row of the area to print
-    * @param integer $first_col First column of the area to print
-    * @param integer $last_row  Last row of the area to print
-    * @param integer $last_col  Last column of the area to print
-    */
-    function printArea($first_row, $first_col, $last_row, $last_col)
-    {
-        $this->print_rowmin  = $first_row;
-        $this->print_colmin  = $first_col;
-        $this->print_rowmax  = $last_row;
-        $this->print_colmax  = $last_col;
-    }
-
-
-    /**
-    * Set the option to hide gridlines on the printed page.
-    *
-    * @access public
-    */
-    function hideGridlines()
-    {
-        $this->_print_gridlines = 0;
-    }
-
-    /**
-    * Set the option to hide gridlines on the worksheet (as seen on the screen).
-    *
-    * @access public
-    */
-    function hideScreenGridlines()
-    {
-        $this->_screen_gridlines = 0;
-    }
-
-    /**
-    * Set the option to print the row and column headers on the printed page.
-    *
-    * @access public
-    * @param integer $print Whether to print the headers or not. Defaults to 1 (print).
-    */
-    function printRowColHeaders($print = 1)
-    {
-        $this->_print_headers = $print;
-    }
-
-    /**
-    * Set the vertical and horizontal number of pages that will define the maximum area printed.
-    * It doesn't seem to work with OpenOffice.
-    *
-    * @access public
-    * @param  integer $width  Maximun width of printed area in pages
-    * @param  integer $height Maximun heigth of printed area in pages
-    * @see setPrintScale()
-    */
-    function fitToPages($width, $height)
-    {
-        $this->_fit_page      = 1;
-        $this->_fit_width     = $width;
-        $this->_fit_height    = $height;
-    }
-
-    /**
-    * Store the horizontal page breaks on a worksheet (for printing).
-    * The breaks represent the row after which the break is inserted.
-    *
-    * @access public
-    * @param array $breaks Array containing the horizontal page breaks
-    */
-    function setHPagebreaks($breaks)
-    {
-        foreach ($breaks as $break) {
-            array_push($this->_hbreaks, $break);
-        }
-    }
-
-    /**
-    * Store the vertical page breaks on a worksheet (for printing).
-    * The breaks represent the column after which the break is inserted.
-    *
-    * @access public
-    * @param array $breaks Array containing the vertical page breaks
-    */
-    function setVPagebreaks($breaks)
-    {
-        foreach ($breaks as $break) {
-            array_push($this->_vbreaks, $break);
-        }
-    }
-
-
-    /**
-    * Set the worksheet zoom factor.
-    *
-    * @access public
-    * @param integer $scale The zoom factor
-    */
-    function setZoom($scale = 100)
-    {
-        // Confine the scale to Excel's range
-        if ($scale < 10 || $scale > 400) {
-            $this->raiseError("Zoom factor $scale outside range: 10 <= zoom <= 400");
-            $scale = 100;
-        }
-
-        $this->_zoom = floor($scale);
-    }
-
-    /**
-    * Set the scale factor for the printed page.
-    * It turns off the "fit to page" option
-    *
-    * @access public
-    * @param integer $scale The optional scale factor. Defaults to 100
-    */
-    function setPrintScale($scale = 100)
-    {
-        // Confine the scale to Excel's range
-        if ($scale < 10 || $scale > 400) {
-            $this->raiseError("Print scale $scale outside range: 10 <= zoom <= 400");
-            $scale = 100;
-        }
-
-        // Turn off "fit to page" option
-        $this->_fit_page = 0;
-
-        $this->_print_scale = floor($scale);
-    }
-
-    /**
-    * Map to the appropriate write method acording to the token recieved.
-    *
-    * @access public
-    * @param integer $row    The row of the cell we are writing to
-    * @param integer $col    The column of the cell we are writing to
-    * @param mixed   $token  What we are writing
-    * @param mixed   $format The optional format to apply to the cell
-    */
-    function write($row, $col, $token, $format = null)
-    {
-        // Check for a cell reference in A1 notation and substitute row and column
-        /*if ($_[0] =~ /^\D/) {
-            @_ = $this->_substituteCellref(@_);
-    }*/
-
-        if (preg_match("/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/", $token)) {
-            // Match number
-            return $this->writeNumber($row, $col, $token, $format);
-        } elseif (preg_match("/^[fh]tt?p:\/\//", $token)) {
-            // Match http or ftp URL
-            return $this->writeUrl($row, $col, $token, '', $format);
-        } elseif (preg_match("/^mailto:/", $token)) {
-            // Match mailto:
-            return $this->writeUrl($row, $col, $token, '', $format);
-        } elseif (preg_match("/^(?:in|ex)ternal:/", $token)) {
-            // Match internal or external sheet link
-            return $this->writeUrl($row, $col, $token, '', $format);
-        } elseif (preg_match("/^=/", $token)) {
-            // Match formula
-            return $this->writeFormula($row, $col, $token, $format);
-        } elseif ($token == '') {
-            // Match blank
-            return $this->writeBlank($row, $col, $format);
-        } else {
-            // Default: match string
-            return $this->writeString($row, $col, $token, $format);
-        }
-    }
-
-    /**
-    * Write an array of values as a row
-    *
-    * @access public
-    * @param integer $row    The row we are writing to
-    * @param integer $col    The first col (leftmost col) we are writing to
-    * @param array   $val    The array of values to write
-    * @param mixed   $format The optional format to apply to the cell
-    * @return mixed PEAR_Error on failure
-    */
-
-    function writeRow($row, $col, $val, $format = null)
-    {
-        $retval = '';
-        if (is_array($val)) {
-            foreach ($val as $v) {
-                if (is_array($v)) {
-                    $this->writeCol($row, $col, $v, $format);
-                } else {
-                    $this->write($row, $col, $v, $format);
-                }
-                $col++;
-            }
-        } else {
-            $retval = new PEAR_Error('$val needs to be an array');
-        }
-        return($retval);
-    }
-
-    /**
-    * Write an array of values as a column
-    *
-    * @access public
-    * @param integer $row    The first row (uppermost row) we are writing to
-    * @param integer $col    The col we are writing to
-    * @param array   $val    The array of values to write
-    * @param mixed   $format The optional format to apply to the cell
-    * @return mixed PEAR_Error on failure
-    */
-
-    function writeCol($row, $col, $val, $format = null)
-    {
-        $retval = '';
-        if (is_array($val)) {
-            foreach ($val as $v) {
-                $this->write($row, $col, $v, $format);
-                $row++;
-            }
-        } else {
-            $retval = new PEAR_Error('$val needs to be an array');
-        }
-        return($retval);
-    }
-
-    /**
-    * Returns an index to the XF record in the workbook
-    *
-    * @access private
-    * @param mixed &$format The optional XF format
-    * @return integer The XF record index
-    */
-    function _XF(&$format)
-    {
-        if ($format) {
-            return($format->getXfIndex());
-        } else {
-            return(0x0F);
-        }
-    }
-
-
-    /******************************************************************************
-    *******************************************************************************
-    *
-    * Internal methods
-    */
-
-
-    /**
-    * Store Worksheet data in memory using the parent's class append() or to a
-    * temporary file, the default.
-    *
-    * @access private
-    * @param string $data The binary data to append
-    */
-    function _append($data)
-    {
-        if ($this->_using_tmpfile) {
-            // Add CONTINUE records if necessary
-            if (strlen($data) > $this->_limit) {
-                $data = $this->_addContinue($data);
-            }
-            fwrite($this->_filehandle, $data);
-            $this->_datasize += strlen($data);
-        } else {
-            parent::_append($data);
-        }
-    }
-
-    /**
-    * Substitute an Excel cell reference in A1 notation for  zero based row and
-    * column values in an argument list.
-    *
-    * Ex: ("A4", "Hello") is converted to (3, 0, "Hello").
-    *
-    * @access private
-    * @param string $cell The cell reference. Or range of cells.
-    * @return array
-    */
-    function _substituteCellref($cell)
-    {
-        $cell = strtoupper($cell);
-
-        // Convert a column range: 'A:A' or 'B:G'
-        if (preg_match("/([A-I]?[A-Z]):([A-I]?[A-Z])/", $cell, $match)) {
-            list($no_use, $col1) =  $this->_cellToRowcol($match[1] .'1'); // Add a dummy row
-            list($no_use, $col2) =  $this->_cellToRowcol($match[2] .'1'); // Add a dummy row
-            return(array($col1, $col2));
-        }
-
-        // Convert a cell range: 'A1:B7'
-        if (preg_match("/\$?([A-I]?[A-Z]\$?\d+):\$?([A-I]?[A-Z]\$?\d+)/", $cell, $match)) {
-            list($row1, $col1) =  $this->_cellToRowcol($match[1]);
-            list($row2, $col2) =  $this->_cellToRowcol($match[2]);
-            return(array($row1, $col1, $row2, $col2));
-        }
-
-        // Convert a cell reference: 'A1' or 'AD2000'
-        if (preg_match("/\$?([A-I]?[A-Z]\$?\d+)/", $cell)) {
-            list($row1, $col1) =  $this->_cellToRowcol($match[1]);
-            return(array($row1, $col1));
-        }
-
-        // TODO use real error codes
-        $this->raiseError("Unknown cell reference $cell", 0, PEAR_ERROR_DIE);
-    }
-
-    /**
-    * Convert an Excel cell reference in A1 notation to a zero based row and column
-    * reference; converts C1 to (0, 2).
-    *
-    * @access private
-    * @param string $cell The cell reference.
-    * @return array containing (row, column)
-    */
-    function _cellToRowcol($cell)
-    {
-        preg_match("/\$?([A-I]?[A-Z])\$?(\d+)/",$cell,$match);
-        $col     = $match[1];
-        $row     = $match[2];
-
-        // Convert base26 column string to number
-        $chars = split('', $col);
-        $expn  = 0;
-        $col   = 0;
-
-        while ($chars) {
-            $char = array_pop($chars);        // LS char first
-            $col += (ord($char) -ord('A') +1) * pow(26,$expn);
-            $expn++;
-        }
-
-        // Convert 1-index to zero-index
-        $row--;
-        $col--;
-
-        return(array($row, $col));
-    }
-
-    /**
-    * Based on the algorithm provided by Daniel Rentz of OpenOffice.
-    *
-    * @access private
-    * @param string $plaintext The password to be encoded in plaintext.
-    * @return string The encoded password
-    */
-    function _encodePassword($plaintext)
-    {
-        $password = 0x0000;
-        $i        = 1;       // char position
-
-        // split the plain text password in its component characters
-        $chars = preg_split('//', $plaintext, -1, PREG_SPLIT_NO_EMPTY);
-        foreach ($chars as $char) {
-            $value        = ord($char) << $i;   // shifted ASCII value
-            $rotated_bits = $value >> 15;       // rotated bits beyond bit 15
-            $value       &= 0x7fff;             // first 15 bits
-            $password    ^= ($value | $rotated_bits);
-            $i++;
-        }
-
-        $password ^= strlen($plaintext);
-        $password ^= 0xCE4B;
-
-        return($password);
-    }
-
-    /**
-    * This method sets the properties for outlining and grouping. The defaults
-    * correspond to Excel's defaults.
-    *
-    * @param bool $visible
-    * @param bool $symbols_below
-    * @param bool $symbols_right
-    * @param bool $auto_style
-    */
-    function setOutline($visible = true, $symbols_below = true, $symbols_right = true, $auto_style = false)
-    {
-        $this->_outline_on    = $visible;
-        $this->_outline_below = $symbols_below;
-        $this->_outline_right = $symbols_right;
-        $this->_outline_style = $auto_style;
-
-        // Ensure this is a boolean vale for Window2
-        if ($this->_outline_on) {
-            $this->_outline_on = 1;
-        }
-     }
-
-    /******************************************************************************
-    *******************************************************************************
-    *
-    * BIFF RECORDS
-    */
-
-
-    /**
-    * Write a double to the specified row and column (zero indexed).
-    * An integer can be written as a double. Excel will display an
-    * integer. $format is optional.
-    *
-    * Returns  0 : normal termination
-    *         -2 : row or column out of range
-    *
-    * @access public
-    * @param integer $row    Zero indexed row
-    * @param integer $col    Zero indexed column
-    * @param float   $num    The number to write
-    * @param mixed   $format The optional XF format
-    * @return integer
-    */
-    function writeNumber($row, $col, $num, $format = null)
-    {
-        $record    = 0x0203;                 // Record identifier
-        $length    = 0x000E;                 // Number of bytes to follow
-
-        $xf        = $this->_XF($format);    // The cell format
-
-        // Check that row and col are valid and store max and min values
-        if ($row >= $this->_xls_rowmax) {
-            return(-2);
-        }
-        if ($col >= $this->_xls_colmax) {
-            return(-2);
-        }
-        if ($row <  $this->_dim_rowmin)  {
-            $this->_dim_rowmin = $row;
-        }
-        if ($row >  $this->_dim_rowmax)  {
-            $this->_dim_rowmax = $row;
-        }
-        if ($col <  $this->_dim_colmin)  {
-            $this->_dim_colmin = $col;
-        }
-        if ($col >  $this->_dim_colmax)  {
-            $this->_dim_colmax = $col;
-        }
-
-        $header    = pack("vv",  $record, $length);
-        $data      = pack("vvv", $row, $col, $xf);
-        $xl_double = pack("d",   $num);
-        if ($this->_byte_order) { // if it's Big Endian
-            $xl_double = strrev($xl_double);
-        }
-
-        $this->_append($header.$data.$xl_double);
-        return(0);
-    }
-
-    /**
-    * Write a string to the specified row and column (zero indexed).
-    * NOTE: there is an Excel 5 defined limit of 255 characters.
-    * $format is optional.
-    * Returns  0 : normal termination
-    *         -2 : row or column out of range
-    *         -3 : long string truncated to 255 chars
-    *
-    * @access public
-    * @param integer $row    Zero indexed row
-    * @param integer $col    Zero indexed column
-    * @param string  $str    The string to write
-    * @param mixed   $format The XF format for the cell
-    * @return integer
-    */
-    function writeString($row, $col, $str, $format = null)
-    {
-        if ($this->_BIFF_version == 0x0600) {
-            return $this->writeStringBIFF8($row, $col, $str, $format);
-        }
-        $strlen    = strlen($str);
-        $record    = 0x0204;                   // Record identifier
-        $length    = 0x0008 + $strlen;         // Bytes to follow
-        $xf        = $this->_XF($format);      // The cell format
-
-        $str_error = 0;
-
-        // Check that row and col are valid and store max and min values
-        if ($row >= $this->_xls_rowmax) {
-            return(-2);
-        }
-        if ($col >= $this->_xls_colmax) {
-            return(-2);
-        }
-        if ($row <  $this->_dim_rowmin) {
-            $this->_dim_rowmin = $row;
-        }
-        if ($row >  $this->_dim_rowmax) {
-            $this->_dim_rowmax = $row;
-        }
-        if ($col <  $this->_dim_colmin) {
-            $this->_dim_colmin = $col;
-        }
-        if ($col >  $this->_dim_colmax) {
-            $this->_dim_colmax = $col;
-        }
-
-        if ($strlen > $this->_xls_strmax) { // LABEL must be < 255 chars
-            $str       = substr($str, 0, $this->_xls_strmax);
-            $length    = 0x0008 + $this->_xls_strmax;
-            $strlen    = $this->_xls_strmax;
-            $str_error = -3;
-        }
-
-        $header    = pack("vv",   $record, $length);
-        $data      = pack("vvvv", $row, $col, $xf, $strlen);
-        $this->_append($header . $data . $str);
-        return($str_error);
-    }
-
-    /**
-    * Sets Input Encoding for writing strings
-    *
-    * @access public
-    * @param string $encoding The encoding. Ex: 'UTF-16LE', 'utf-8', 'ISO-859-7'
-    */
-    function setInputEncoding($encoding)
-    {
-         // Modified by Ivan Tcholakov, 06-AUG-2010.
-         //if ($encoding != 'UTF-16LE' && !function_exists('iconv')) {
-         if (!api_equal_encodings($encoding, 'UTF-16LE') && !api_is_encoding_supported($encoding)) {
-         //
-             $this->raiseError("Using an input encoding other than UTF-16LE requires PHP support for iconv");
-         }
-         $this->_input_encoding = $encoding;
-    }
-
-    /**
-    * Write a string to the specified row and column (zero indexed).
-    * This is the BIFF8 version (no 255 chars limit).
-    * $format is optional.
-    * Returns  0 : normal termination
-    *         -2 : row or column out of range
-    *         -3 : long string truncated to 255 chars
-    *
-    * @access public
-    * @param integer $row    Zero indexed row
-    * @param integer $col    Zero indexed column
-    * @param string  $str    The string to write
-    * @param mixed   $format The XF format for the cell
-    * @return integer
-    */
-    function writeStringBIFF8($row, $col, $str, $format = null)
-    {
-        // Modified by Ivan Tcholakov, 06-AUG-2010.
-        //if ($this->_input_encoding == 'UTF-16LE')
-        if (api_equal_encodings($this->_input_encoding, 'UTF-16LE'))
-        //
-        {
-            // Modified by Ivan Tcholakov, 06-AUG-2010.
-            //$strlen = function_exists('mb_strlen') ? mb_strlen($str, 'UTF-16LE') : (strlen($str) / 2);
-            $strlen = api_is_encoding_supported('UTF-16LE') ? api_strlen($str, 'UTF-16LE') : (strlen($str) / 2);
-            //
-            $encoding  = 0x1;
-        }
-        elseif ($this->_input_encoding != '')
-        {
-            // Modified by Ivan Tcholakov, 06-AUG-2010.
-            //$str = iconv($this->_input_encoding, 'UTF-16LE', $str);
-            //$strlen = function_exists('mb_strlen') ? mb_strlen($str, 'UTF-16LE') : (strlen($str) / 2);
-            $str = api_convert_encoding($str, 'UTF-16LE', $this->_input_encoding);
-            $strlen = api_is_encoding_supported('UTF-16LE') ? api_strlen($str, 'UTF-16LE') : (strlen($str) / 2);
-            //
-            $encoding  = 0x1;
-        }
-        else
-        {
-            $strlen    = strlen($str);
-            $encoding  = 0x0;
-        }
-        $record    = 0x00FD;                   // Record identifier
-        $length    = 0x000A;                   // Bytes to follow
-        $xf        = $this->_XF($format);      // The cell format
-
-        $str_error = 0;
-
-        // Check that row and col are valid and store max and min values
-        if ($this->_checkRowCol($row, $col) == false) {
-            return -2;
-        }
-
-        $str = pack('vC', $strlen, $encoding).$str;
-
-        /* check if string is already present */
-        if (!isset($this->_str_table[$str])) {
-            $this->_str_table[$str] = $this->_str_unique++;
-        }
-        $this->_str_total++;
-
-        $header    = pack('vv',   $record, $length);
-        $data      = pack('vvvV', $row, $col, $xf, $this->_str_table[$str]);
-        $this->_append($header.$data);
-        return $str_error;
-    }
-
-    /**
-    * Check row and col before writing to a cell, and update the sheet's
-    * dimensions accordingly
-    *
-    * @access private
-    * @param integer $row    Zero indexed row
-    * @param integer $col    Zero indexed column
-    * @return boolean true for success, false if row and/or col are grester
-    *                 then maximums allowed.
-    */
-    function _checkRowCol($row, $col)
-    {
-        if ($row >= $this->_xls_rowmax) {
-            return false;
-        }
-        if ($col >= $this->_xls_colmax) {
-            return false;
-        }
-        if ($row <  $this->_dim_rowmin) {
-            $this->_dim_rowmin = $row;
-        }
-        if ($row >  $this->_dim_rowmax) {
-            $this->_dim_rowmax = $row;
-        }
-        if ($col <  $this->_dim_colmin) {
-            $this->_dim_colmin = $col;
-        }
-        if ($col >  $this->_dim_colmax) {
-            $this->_dim_colmax = $col;
-        }
-        return true;
-    }
-
-    /**
-    * Writes a note associated with the cell given by the row and column.
-    * NOTE records don't have a length limit.
-    *
-    * @access public
-    * @param integer $row    Zero indexed row
-    * @param integer $col    Zero indexed column
-    * @param string  $note   The note to write
-    */
-    function writeNote($row, $col, $note)
-    {
-        $note_length    = strlen($note);
-        $record         = 0x001C;                // Record identifier
-        $max_length     = 2048;                  // Maximun length for a NOTE record
-        //$length      = 0x0006 + $note_length;    // Bytes to follow
-
-        // Check that row and col are valid and store max and min values
-        if ($row >= $this->_xls_rowmax) {
-            return(-2);
-        }
-        if ($col >= $this->_xls_colmax) {
-            return(-2);
-        }
-        if ($row <  $this->_dim_rowmin) {
-            $this->_dim_rowmin = $row;
-        }
-        if ($row >  $this->_dim_rowmax) {
-            $this->_dim_rowmax = $row;
-        }
-        if ($col <  $this->_dim_colmin) {
-            $this->_dim_colmin = $col;
-        }
-        if ($col >  $this->_dim_colmax) {
-            $this->_dim_colmax = $col;
-        }
-
-        // Length for this record is no more than 2048 + 6
-        $length    = 0x0006 + min($note_length, 2048);
-        $header    = pack("vv",   $record, $length);
-        $data      = pack("vvv", $row, $col, $note_length);
-        $this->_append($header . $data . substr($note, 0, 2048));
-
-        for ($i = $max_length; $i < $note_length; $i += $max_length) {
-            $chunk  = substr($note, $i, $max_length);
-            $length = 0x0006 + strlen($chunk);
-            $header = pack("vv",   $record, $length);
-            $data   = pack("vvv", -1, 0, strlen($chunk));
-            $this->_append($header.$data.$chunk);
-        }
-        return(0);
-    }
-
-    /**
-    * Write a blank cell to the specified row and column (zero indexed).
-    * A blank cell is used to specify formatting without adding a string
-    * or a number.
-    *
-    * A blank cell without a format serves no purpose. Therefore, we don't write
-    * a BLANK record unless a format is specified.
-    *
-    * Returns  0 : normal termination (including no format)
-    *         -1 : insufficient number of arguments
-    *         -2 : row or column out of range
-    *
-    * @access public
-    * @param integer $row    Zero indexed row
-    * @param integer $col    Zero indexed column
-    * @param mixed   $format The XF format
-    */
-    function writeBlank($row, $col, $format)
-    {
-        // Don't write a blank cell unless it has a format
-        if (!$format) {
-            return(0);
-        }
-
-        $record    = 0x0201;                 // Record identifier
-        $length    = 0x0006;                 // Number of bytes to follow
-        $xf        = $this->_XF($format);    // The cell format
-
-        // Check that row and col are valid and store max and min values
-        if ($row >= $this->_xls_rowmax) {
-            return(-2);
-        }
-        if ($col >= $this->_xls_colmax) {
-            return(-2);
-        }
-        if ($row <  $this->_dim_rowmin) {
-            $this->_dim_rowmin = $row;
-        }
-        if ($row >  $this->_dim_rowmax) {
-            $this->_dim_rowmax = $row;
-        }
-        if ($col <  $this->_dim_colmin) {
-            $this->_dim_colmin = $col;
-        }
-        if ($col >  $this->_dim_colmax) {
-            $this->_dim_colmax = $col;
-        }
-
-        $header    = pack("vv",  $record, $length);
-        $data      = pack("vvv", $row, $col, $xf);
-        $this->_append($header . $data);
-        return 0;
-    }
-
-    /**
-    * Write a formula to the specified row and column (zero indexed).
-    * The textual representation of the formula is passed to the parser in
-    * Parser.php which returns a packed binary string.
-    *
-    * Returns  0 : normal termination
-    *         -1 : formula errors (bad formula)
-    *         -2 : row or column out of range
-    *
-    * @access public
-    * @param integer $row     Zero indexed row
-    * @param integer $col     Zero indexed column
-    * @param string  $formula The formula text string
-    * @param mixed   $format  The optional XF format
-    * @return integer
-    */
-    function writeFormula($row, $col, $formula, $format = null)
-    {
-        $record    = 0x0006;     // Record identifier
-
-        // Excel normally stores the last calculated value of the formula in $num.
-        // Clearly we are not in a position to calculate this a priori. Instead
-        // we set $num to zero and set the option flags in $grbit to ensure
-        // automatic calculation of the formula when the file is opened.
-        //
-        $xf        = $this->_XF($format); // The cell format
-        $num       = 0x00;                // Current value of formula
-        $grbit     = 0x03;                // Option flags
-        $unknown   = 0x0000;              // Must be zero
-
-
-        // Check that row and col are valid and store max and min values
-        if ($this->_checkRowCol($row, $col) == false) {
-            return -2;
-        }
-
-        // Strip the '=' or '@' sign at the beginning of the formula string
-        if (preg_match("/^=/", $formula)) {
-            $formula = preg_replace("/(^=)/", "", $formula);
-        } elseif (preg_match("/^@/", $formula)) {
-            $formula = preg_replace("/(^@)/", "", $formula);
-        } else {
-            // Error handling
-            $this->writeString($row, $col, 'Unrecognised character for formula');
-            return -1;
-        }
-
-        // Parse the formula using the parser in Parser.php
-        $error = $this->_parser->parse($formula);
-        if ($this->isError($error)) {
-            $this->writeString($row, $col, $error->getMessage());
-            return -1;
-        }
-
-        $formula = $this->_parser->toReversePolish();
-        if ($this->isError($formula)) {
-            $this->writeString($row, $col, $formula->getMessage());
-            return -1;
-        }
-
-        $formlen    = strlen($formula);    // Length of the binary string
-        $length     = 0x16 + $formlen;     // Length of the record data
-
-        $header    = pack("vv",      $record, $length);
-        $data      = pack("vvvdvVv", $row, $col, $xf, $num,
-                                     $grbit, $unknown, $formlen);
-
-        $this->_append($header . $data . $formula);
-        return 0;
-    }
-
-    /**
-    * Write a hyperlink.
-    * This is comprised of two elements: the visible label and
-    * the invisible link. The visible label is the same as the link unless an
-    * alternative string is specified. The label is written using the
-    * writeString() method. Therefore the 255 characters string limit applies.
-    * $string and $format are optional.
-    *
-    * The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external
-    * directory url.
-    *
-    * Returns  0 : normal termination
-    *         -2 : row or column out of range
-    *         -3 : long string truncated to 255 chars
-    *
-    * @access public
-    * @param integer $row    Row
-    * @param integer $col    Column
-    * @param string  $url    URL string
-    * @param string  $string Alternative label
-    * @param mixed   $format The cell format
-    * @return integer
-    */
-    function writeUrl($row, $col, $url, $string = '', $format = null)
-    {
-        // Add start row and col to arg list
-        return($this->_writeUrlRange($row, $col, $row, $col, $url, $string, $format));
-    }
-
-    /**
-    * This is the more general form of writeUrl(). It allows a hyperlink to be
-    * written to a range of cells. This function also decides the type of hyperlink
-    * to be written. These are either, Web (http, ftp, mailto), Internal
-    * (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1').
-    *
-    * @access private
-    * @see writeUrl()
-    * @param integer $row1   Start row
-    * @param integer $col1   Start column
-    * @param integer $row2   End row
-    * @param integer $col2   End column
-    * @param string  $url    URL string
-    * @param string  $string Alternative label
-    * @param mixed   $format The cell format
-    * @return integer
-    */
-
-    function _writeUrlRange($row1, $col1, $row2, $col2, $url, $string = '', $format = null)
-    {
-
-        // Check for internal/external sheet links or default to web link
-        if (preg_match('[^internal:]', $url)) {
-            return($this->_writeUrlInternal($row1, $col1, $row2, $col2, $url, $string, $format));
-        }
-        if (preg_match('[^external:]', $url)) {
-            return($this->_writeUrlExternal($row1, $col1, $row2, $col2, $url, $string, $format));
-        }
-        return($this->_writeUrlWeb($row1, $col1, $row2, $col2, $url, $string, $format));
-    }
-
-
-    /**
-    * Used to write http, ftp and mailto hyperlinks.
-    * The link type ($options) is 0x03 is the same as absolute dir ref without
-    * sheet. However it is differentiated by the $unknown2 data stream.
-    *
-    * @access private
-    * @see writeUrl()
-    * @param integer $row1   Start row
-    * @param integer $col1   Start column
-    * @param integer $row2   End row
-    * @param integer $col2   End column
-    * @param string  $url    URL string
-    * @param string  $str    Alternative label
-    * @param mixed   $format The cell format
-    * @return integer
-    */
-    function _writeUrlWeb($row1, $col1, $row2, $col2, $url, $str, $format = null)
-    {
-        $record      = 0x01B8;                       // Record identifier
-        $length      = 0x00000;                      // Bytes to follow
-
-        if (!$format) {
-            $format = $this->_url_format;
-        }
-
-        // Write the visible label using the writeString() method.
-        if ($str == '') {
-            $str = $url;
-        }
-        $str_error = $this->writeString($row1, $col1, $str, $format);
-        if (($str_error == -2) || ($str_error == -3)) {
-            return $str_error;
-        }
-
-        // Pack the undocumented parts of the hyperlink stream
-        $unknown1    = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000");
-        $unknown2    = pack("H*", "E0C9EA79F9BACE118C8200AA004BA90B");
-
-        // Pack the option flags
-        $options     = pack("V", 0x03);
-
-        // Convert URL to a null terminated wchar string
-        $url         = join("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY));
-        $url         = $url . "\0\0\0";
-
-        // Pack the length of the URL
-        $url_len     = pack("V", strlen($url));
-
-        // Calculate the data length
-        $length      = 0x34 + strlen($url);
-
-        // Pack the header data
-        $header      = pack("vv",   $record, $length);
-        $data        = pack("vvvv", $row1, $row2, $col1, $col2);
-
-        // Write the packed data
-        $this->_append($header . $data .
-                       $unknown1 . $options .
-                       $unknown2 . $url_len . $url);
-        return($str_error);
-    }
-
-    /**
-    * Used to write internal reference hyperlinks such as "Sheet1!A1".
-    *
-    * @access private
-    * @see writeUrl()
-    * @param integer $row1   Start row
-    * @param integer $col1   Start column
-    * @param integer $row2   End row
-    * @param integer $col2   End column
-    * @param string  $url    URL string
-    * @param string  $str    Alternative label
-    * @param mixed   $format The cell format
-    * @return integer
-    */
-    function _writeUrlInternal($row1, $col1, $row2, $col2, $url, $str, $format = null)
-    {
-        $record      = 0x01B8;                       // Record identifier
-        $length      = 0x00000;                      // Bytes to follow
-
-        if (!$format) {
-            $format = $this->_url_format;
-        }
-
-        // Strip URL type
-        $url = preg_replace('/^internal:/', '', $url);
-
-        // Write the visible label
-        if ($str == '') {
-            $str = $url;
-        }
-        $str_error = $this->writeString($row1, $col1, $str, $format);
-        if (($str_error == -2) || ($str_error == -3)) {
-            return $str_error;
-        }
-
-        // Pack the undocumented parts of the hyperlink stream
-        $unknown1    = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000");
-
-        // Pack the option flags
-        $options     = pack("V", 0x08);
-
-        // Convert the URL type and to a null terminated wchar string
-        $url         = join("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY));
-        $url         = $url . "\0\0\0";
-
-        // Pack the length of the URL as chars (not wchars)
-        $url_len     = pack("V", floor(strlen($url)/2));
-
-        // Calculate the data length
-        $length      = 0x24 + strlen($url);
-
-        // Pack the header data
-        $header      = pack("vv",   $record, $length);
-        $data        = pack("vvvv", $row1, $row2, $col1, $col2);
-
-        // Write the packed data
-        $this->_append($header . $data .
-                       $unknown1 . $options .
-                       $url_len . $url);
-        return($str_error);
-    }
-
-    /**
-    * Write links to external directory names such as 'c:\foo.xls',
-    * c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'.
-    *
-    * Note: Excel writes some relative links with the $dir_long string. We ignore
-    * these cases for the sake of simpler code.
-    *
-    * @access private
-    * @see writeUrl()
-    * @param integer $row1   Start row
-    * @param integer $col1   Start column
-    * @param integer $row2   End row
-    * @param integer $col2   End column
-    * @param string  $url    URL string
-    * @param string  $str    Alternative label
-    * @param mixed   $format The cell format
-    * @return integer
-    */
-    function _writeUrlExternal($row1, $col1, $row2, $col2, $url, $str, $format = null)
-    {
-        // Network drives are different. We will handle them separately
-        // MS/Novell network drives and shares start with \\
-        if (preg_match('[^external:\\\\]', $url)) {
-            return; //($this->_writeUrlExternal_net($row1, $col1, $row2, $col2, $url, $str, $format));
-        }
-
-        $record      = 0x01B8;                       // Record identifier
-        $length      = 0x00000;                      // Bytes to follow
-
-        if (!$format) {
-            $format = $this->_url_format;
-        }
-
-        // Strip URL type and change Unix dir separator to Dos style (if needed)
-        //
-        $url = preg_replace('/^external:/', '', $url);
-        $url = preg_replace('/\//', "\\", $url);
-
-        // Write the visible label
-        if ($str == '') {
-            $str = preg_replace('/\#/', ' - ', $url);
-        }
-        $str_error = $this->writeString($row1, $col1, $str, $format);
-        if (($str_error == -2) or ($str_error == -3)) {
-            return $str_error;
-        }
-
-        // Determine if the link is relative or absolute:
-        //   relative if link contains no dir separator, "somefile.xls"
-        //   relative if link starts with up-dir, "..\..\somefile.xls"
-        //   otherwise, absolute
-
-        $absolute    = 0x02; // Bit mask
-        if (!preg_match("/\\\/", $url)) {
-            $absolute    = 0x00;
-        }
-        if (preg_match("/^\.\.\\\/", $url)) {
-            $absolute    = 0x00;
-        }
-        $link_type               = 0x01 | $absolute;
-
-        // Determine if the link contains a sheet reference and change some of the
-        // parameters accordingly.
-        // Split the dir name and sheet name (if it exists)
-        /*if (preg_match("/\#/", $url)) {
-            list($dir_long, $sheet) = split("\#", $url);
-        } else {
-            $dir_long = $url;
-        }
-
-        if (isset($sheet)) {
-            $link_type |= 0x08;
-            $sheet_len  = pack("V", strlen($sheet) + 0x01);
-            $sheet      = join("\0", split('', $sheet));
-            $sheet     .= "\0\0\0";
-        } else {
-            $sheet_len   = '';
-            $sheet       = '';
-        }*/
-        $dir_long = $url;
-        if (preg_match("/\#/", $url)) {
-            $link_type |= 0x08;
-        }
-
-
-
-        // Pack the link type
-        $link_type   = pack("V", $link_type);
-
-        // Calculate the up-level dir count e.g.. (..\..\..\ == 3)
-        $up_count    = preg_match_all("/\.\.\\\/", $dir_long, $useless);
-        $up_count    = pack("v", $up_count);
-
-        // Store the short dos dir name (null terminated)
-        $dir_short   = preg_replace("/\.\.\\\/", '', $dir_long) . "\0";
-
-        // Store the long dir name as a wchar string (non-null terminated)
-        //$dir_long       = join("\0", split('', $dir_long));
-        $dir_long       = $dir_long . "\0";
-
-        // Pack the lengths of the dir strings
-        $dir_short_len = pack("V", strlen($dir_short)      );
-        $dir_long_len  = pack("V", strlen($dir_long)       );
-        $stream_len    = pack("V", 0);//strlen($dir_long) + 0x06);
-
-        // Pack the undocumented parts of the hyperlink stream
-        $unknown1 = pack("H*",'D0C9EA79F9BACE118C8200AA004BA90B02000000'       );
-        $unknown2 = pack("H*",'0303000000000000C000000000000046'               );
-        $unknown3 = pack("H*",'FFFFADDE000000000000000000000000000000000000000');
-        $unknown4 = pack("v",  0x03                                            );
-
-        // Pack the main data stream
-        $data        = pack("vvvv", $row1, $row2, $col1, $col2) .
-                          $unknown1     .
-                          $link_type    .
-                          $unknown2     .
-                          $up_count     .
-                          $dir_short_len.
-                          $dir_short    .
-                          $unknown3     .
-                          $stream_len   ;/*.
-                          $dir_long_len .
-                          $unknown4     .
-                          $dir_long     .
-                          $sheet_len    .
-                          $sheet        ;*/
-
-        // Pack the header data
-        $length   = strlen($data);
-        $header   = pack("vv", $record, $length);
-
-        // Write the packed data
-        $this->_append($header. $data);
-        return($str_error);
-    }
-
-
-    /**
-    * This method is used to set the height and format for a row.
-    *
-    * @access public
-    * @param integer $row    The row to set
-    * @param integer $height Height we are giving to the row.
-    *                        Use null to set XF without setting height
-    * @param mixed   $format XF format we are giving to the row
-    * @param bool    $hidden The optional hidden attribute
-    * @param integer $level  The optional outline level for row, in range [0,7]
-    */
-    function setRow($row, $height, $format = null, $hidden = false, $level = 0)
-    {
-        $record      = 0x0208;               // Record identifier
-        $length      = 0x0010;               // Number of bytes to follow
-
-        $colMic      = 0x0000;               // First defined column
-        $colMac      = 0x0000;               // Last defined column
-        $irwMac      = 0x0000;               // Used by Excel to optimise loading
-        $reserved    = 0x0000;               // Reserved
-        $grbit       = 0x0000;               // Option flags
-        $ixfe        = $this->_XF($format);  // XF index
-
-        // set _row_sizes so _sizeRow() can use it
-        $this->_row_sizes[$row] = $height;
-
-        // Use setRow($row, null, $XF) to set XF format without setting height
-        if ($height != null) {
-            $miyRw = $height * 20;  // row height
-        } else {
-            $miyRw = 0xff;          // default row height is 256
-        }
-
-        $level = max(0, min($level, 7));  // level should be between 0 and 7
-        $this->_outline_row_level = max($level, $this->_outline_row_level);
-
-
-        // Set the options flags. fUnsynced is used to show that the font and row
-        // heights are not compatible. This is usually the case for WriteExcel.
-        // The collapsed flag 0x10 doesn't seem to be used to indicate that a row
-        // is collapsed. Instead it is used to indicate that the previous row is
-        // collapsed. The zero height flag, 0x20, is used to collapse a row.
-
-        $grbit |= $level;
-        if ($hidden) {
-            $grbit |= 0x0020;
-        }
-        $grbit |= 0x0040; // fUnsynced
-        if ($format) {
-            $grbit |= 0x0080;
-        }
-        $grbit |= 0x0100;
-
-        $header   = pack("vv",       $record, $length);
-        $data     = pack("vvvvvvvv", $row, $colMic, $colMac, $miyRw,
-                                     $irwMac,$reserved, $grbit, $ixfe);
-        $this->_append($header.$data);
-    }
-
-    /**
-    * Writes Excel DIMENSIONS to define the area in which there is data.
-    *
-    * @access private
-    */
-    function _storeDimensions()
-    {
-        $record    = 0x0200;                 // Record identifier
-        $row_min   = $this->_dim_rowmin;     // First row
-        $row_max   = $this->_dim_rowmax + 1; // Last row plus 1
-        $col_min   = $this->_dim_colmin;     // First column
-        $col_max   = $this->_dim_colmax + 1; // Last column plus 1
-        $reserved  = 0x0000;                 // Reserved by Excel
-
-        if ($this->_BIFF_version == 0x0500) {
-            $length    = 0x000A;               // Number of bytes to follow
-            $data      = pack("vvvvv", $row_min, $row_max,
-                                       $col_min, $col_max, $reserved);
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $length    = 0x000E;
-            $data      = pack("VVvvv", $row_min, $row_max,
-                                       $col_min, $col_max, $reserved);
-        }
-        $header = pack("vv", $record, $length);
-        $this->_prepend($header.$data);
-    }
-
-    /**
-    * Write BIFF record Window2.
-    *
-    * @access private
-    */
-    function _storeWindow2()
-    {
-        $record         = 0x023E;     // Record identifier
-        if ($this->_BIFF_version == 0x0500) {
-            $length         = 0x000A;     // Number of bytes to follow
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $length         = 0x0012;
-        }
-
-        $grbit          = 0x00B6;     // Option flags
-        $rwTop          = 0x0000;     // Top row visible in window
-        $colLeft        = 0x0000;     // Leftmost column visible in window
-
-
-        // The options flags that comprise $grbit
-        $fDspFmla       = 0;                     // 0 - bit
-        $fDspGrid       = $this->_screen_gridlines; // 1
-        $fDspRwCol      = 1;                     // 2
-        $fFrozen        = $this->_frozen;        // 3
-        $fDspZeros      = 1;                     // 4
-        $fDefaultHdr    = 1;                     // 5
-        $fArabic        = 0;                     // 6
-        $fDspGuts       = $this->_outline_on;    // 7
-        $fFrozenNoSplit = 0;                     // 0 - bit
-        $fSelected      = $this->selected;       // 1
-        $fPaged         = 1;                     // 2
-
-        $grbit             = $fDspFmla;
-        $grbit            |= $fDspGrid       << 1;
-        $grbit            |= $fDspRwCol      << 2;
-        $grbit            |= $fFrozen        << 3;
-        $grbit            |= $fDspZeros      << 4;
-        $grbit            |= $fDefaultHdr    << 5;
-        $grbit            |= $fArabic        << 6;
-        $grbit            |= $fDspGuts       << 7;
-        $grbit            |= $fFrozenNoSplit << 8;
-        $grbit            |= $fSelected      << 9;
-        $grbit            |= $fPaged         << 10;
-
-        $header  = pack("vv",   $record, $length);
-        $data    = pack("vvv", $grbit, $rwTop, $colLeft);
-        // FIXME !!!
-        if ($this->_BIFF_version == 0x0500) {
-            $rgbHdr         = 0x00000000; // Row/column heading and gridline color
-            $data .= pack("V", $rgbHdr);
-        } elseif ($this->_BIFF_version == 0x0600) {
-            $rgbHdr       = 0x0040; // Row/column heading and gridline color index
-            $zoom_factor_page_break = 0x0000;
-            $zoom_factor_normal     = 0x0000;
-            $data .= pack("vvvvV", $rgbHdr, 0x0000, $zoom_factor_page_break, $zoom_factor_normal, 0x00000000);
-        }
-        $this->_append($header.$data);
-    }
-
-    /**
-    * Write BIFF record DEFCOLWIDTH if COLINFO records are in use.
-    *
-    * @access private
-    */
-    function _storeDefcol()
-    {
-        $record   = 0x0055;      // Record identifier
-        $length   = 0x0002;      // Number of bytes to follow
-        $colwidth = 0x0008;      // Default column width
-
-        $header   = pack("vv", $record, $length);
-        $data     = pack("v",  $colwidth);
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Write BIFF record COLINFO to define column widths
-    *
-    * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C
-    * length record.
-    *
-    * @access private
-    * @param array $col_array This is the only parameter received and is composed of the following:
-    *                0 => First formatted column,
-    *                1 => Last formatted column,
-    *                2 => Col width (8.43 is Excel default),
-    *                3 => The optional XF format of the column,
-    *                4 => Option flags.
-    *                5 => Optional outline level
-    */
-    function _storeColinfo($col_array)
-    {
-        if (isset($col_array[0])) {
-            $colFirst = $col_array[0];
-        }
-        if (isset($col_array[1])) {
-            $colLast = $col_array[1];
-        }
-        if (isset($col_array[2])) {
-            $coldx = $col_array[2];
-        } else {
-            $coldx = 8.43;
-        }
-        if (isset($col_array[3])) {
-            $format = $col_array[3];
-        } else {
-            $format = 0;
-        }
-        if (isset($col_array[4])) {
-            $grbit = $col_array[4];
-        } else {
-            $grbit = 0;
-        }
-        if (isset($col_array[5])) {
-            $level = $col_array[5];
-        } else {
-            $level = 0;
-        }
-        $record   = 0x007D;          // Record identifier
-        $length   = 0x000B;          // Number of bytes to follow
-
-        $coldx   += 0.72;            // Fudge. Excel subtracts 0.72 !?
-        $coldx   *= 256;             // Convert to units of 1/256 of a char
-
-        $ixfe     = $this->_XF($format);
-        $reserved = 0x00;            // Reserved
-
-        $level = max(0, min($level, 7));
-        $grbit |= $level << 8;
-
-        $header   = pack("vv",     $record, $length);
-        $data     = pack("vvvvvC", $colFirst, $colLast, $coldx,
-                                   $ixfe, $grbit, $reserved);
-        $this->_prepend($header.$data);
-    }
-
-    /**
-    * Write BIFF record SELECTION.
-    *
-    * @access private
-    * @param array $array array containing ($rwFirst,$colFirst,$rwLast,$colLast)
-    * @see setSelection()
-    */
-    function _storeSelection($array)
-    {
-        list($rwFirst,$colFirst,$rwLast,$colLast) = $array;
-        $record   = 0x001D;                  // Record identifier
-        $length   = 0x000F;                  // Number of bytes to follow
-
-        $pnn      = $this->_active_pane;     // Pane position
-        $rwAct    = $rwFirst;                // Active row
-        $colAct   = $colFirst;               // Active column
-        $irefAct  = 0;                       // Active cell ref
-        $cref     = 1;                       // Number of refs
-
-        if (!isset($rwLast)) {
-            $rwLast   = $rwFirst;       // Last  row in reference
-        }
-        if (!isset($colLast)) {
-            $colLast  = $colFirst;      // Last  col in reference
-        }
-
-        // Swap last row/col for first row/col as necessary
-        if ($rwFirst > $rwLast) {
-            list($rwFirst, $rwLast) = array($rwLast, $rwFirst);
-        }
-
-        if ($colFirst > $colLast) {
-            list($colFirst, $colLast) = array($colLast, $colFirst);
-        }
-
-        $header   = pack("vv",         $record, $length);
-        $data     = pack("CvvvvvvCC",  $pnn, $rwAct, $colAct,
-                                       $irefAct, $cref,
-                                       $rwFirst, $rwLast,
-                                       $colFirst, $colLast);
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Store the MERGEDCELLS record for all ranges of merged cells
-    *
-    * @access private
-    */
-    function _storeMergedCells()
-    {
-        // if there are no merged cell ranges set, return
-        if (count($this->_merged_ranges) == 0) {
-            return;
-        }
-        $record   = 0x00E5;
-        $length   = 2 + count($this->_merged_ranges) * 8;
-
-        $header   = pack('vv', $record, $length);
-        $data     = pack('v',  count($this->_merged_ranges));
-        foreach ($this->_merged_ranges as $range) {
-            $data .= pack('vvvv', $range[0], $range[2], $range[1], $range[3]);
-        }
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Write BIFF record EXTERNCOUNT to indicate the number of external sheet
-    * references in a worksheet.
-    *
-    * Excel only stores references to external sheets that are used in formulas.
-    * For simplicity we store references to all the sheets in the workbook
-    * regardless of whether they are used or not. This reduces the overall
-    * complexity and eliminates the need for a two way dialogue between the formula
-    * parser the worksheet objects.
-    *
-    * @access private
-    * @param integer $count The number of external sheet references in this worksheet
-    */
-    function _storeExterncount($count)
-    {
-        $record = 0x0016;          // Record identifier
-        $length = 0x0002;          // Number of bytes to follow
-
-        $header = pack("vv", $record, $length);
-        $data   = pack("v",  $count);
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Writes the Excel BIFF EXTERNSHEET record. These references are used by
-    * formulas. A formula references a sheet name via an index. Since we store a
-    * reference to all of the external worksheets the EXTERNSHEET index is the same
-    * as the worksheet index.
-    *
-    * @access private
-    * @param string $sheetname The name of a external worksheet
-    */
-    function _storeExternsheet($sheetname)
-    {
-        $record    = 0x0017;         // Record identifier
-
-        // References to the current sheet are encoded differently to references to
-        // external sheets.
-        //
-        if ($this->name == $sheetname) {
-            $sheetname = '';
-            $length    = 0x02;  // The following 2 bytes
-            $cch       = 1;     // The following byte
-            $rgch      = 0x02;  // Self reference
-        } else {
-            $length    = 0x02 + strlen($sheetname);
-            $cch       = strlen($sheetname);
-            $rgch      = 0x03;  // Reference to a sheet in the current workbook
-        }
-
-        $header = pack("vv",  $record, $length);
-        $data   = pack("CC", $cch, $rgch);
-        $this->_prepend($header . $data . $sheetname);
-    }
-
-    /**
-    * Writes the Excel BIFF PANE record.
-    * The panes can either be frozen or thawed (unfrozen).
-    * Frozen panes are specified in terms of an integer number of rows and columns.
-    * Thawed panes are specified in terms of Excel's units for rows and columns.
-    *
-    * @access private
-    * @param array $panes This is the only parameter received and is composed of the following:
-    *                     0 => Vertical split position,
-    *                     1 => Horizontal split position
-    *                     2 => Top row visible
-    *                     3 => Leftmost column visible
-    *                     4 => Active pane
-    */
-    function _storePanes($panes)
-    {
-        $y       = $panes[0];
-        $x       = $panes[1];
-        $rwTop   = $panes[2];
-        $colLeft = $panes[3];
-        if (count($panes) > 4) { // if Active pane was received
-            $pnnAct = $panes[4];
-        } else {
-            $pnnAct = null;
-        }
-        $record  = 0x0041;       // Record identifier
-        $length  = 0x000A;       // Number of bytes to follow
-
-        // Code specific to frozen or thawed panes.
-        if ($this->_frozen) {
-            // Set default values for $rwTop and $colLeft
-            if (!isset($rwTop)) {
-                $rwTop   = $y;
-            }
-            if (!isset($colLeft)) {
-                $colLeft = $x;
-            }
-        } else {
-            // Set default values for $rwTop and $colLeft
-            if (!isset($rwTop)) {
-                $rwTop   = 0;
-            }
-            if (!isset($colLeft)) {
-                $colLeft = 0;
-            }
-
-            // Convert Excel's row and column units to the internal units.
-            // The default row height is 12.75
-            // The default column width is 8.43
-            // The following slope and intersection values were interpolated.
-            //
-            $y = 20*$y      + 255;
-            $x = 113.879*$x + 390;
-        }
-
-
-        // Determine which pane should be active. There is also the undocumented
-        // option to override this should it be necessary: may be removed later.
-        //
-        if (!isset($pnnAct)) {
-            if ($x != 0 && $y != 0) {
-                $pnnAct = 0; // Bottom right
-            }
-            if ($x != 0 && $y == 0) {
-                $pnnAct = 1; // Top right
-            }
-            if ($x == 0 && $y != 0) {
-                $pnnAct = 2; // Bottom left
-            }
-            if ($x == 0 && $y == 0) {
-                $pnnAct = 3; // Top left
-            }
-        }
-
-        $this->_active_pane = $pnnAct; // Used in _storeSelection
-
-        $header     = pack("vv",    $record, $length);
-        $data       = pack("vvvvv", $x, $y, $rwTop, $colLeft, $pnnAct);
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Store the page setup SETUP BIFF record.
-    *
-    * @access private
-    */
-    function _storeSetup()
-    {
-        $record       = 0x00A1;                  // Record identifier
-        $length       = 0x0022;                  // Number of bytes to follow
-
-        $iPaperSize   = $this->_paper_size;    // Paper size
-        $iScale       = $this->_print_scale;   // Print scaling factor
-        $iPageStart   = 0x01;                 // Starting page number
-        $iFitWidth    = $this->_fit_width;    // Fit to number of pages wide
-        $iFitHeight   = $this->_fit_height;   // Fit to number of pages high
-        $grbit        = 0x00;                 // Option flags
-        $iRes         = 0x0258;               // Print resolution
-        $iVRes        = 0x0258;               // Vertical print resolution
-        $numHdr       = $this->_margin_head;  // Header Margin
-        $numFtr       = $this->_margin_foot;   // Footer Margin
-        $iCopies      = 0x01;                 // Number of copies
-
-        $fLeftToRight = 0x0;                     // Print over then down
-        $fLandscape   = $this->_orientation;     // Page orientation
-        $fNoPls       = 0x0;                     // Setup not read from printer
-        $fNoColor     = 0x0;                     // Print black and white
-        $fDraft       = 0x0;                     // Print draft quality
-        $fNotes       = 0x0;                     // Print notes
-        $fNoOrient    = 0x0;                     // Orientation not set
-        $fUsePage     = 0x0;                     // Use custom starting page
-
-        $grbit           = $fLeftToRight;
-        $grbit          |= $fLandscape    << 1;
-        $grbit          |= $fNoPls        << 2;
-        $grbit          |= $fNoColor      << 3;
-        $grbit          |= $fDraft        << 4;
-        $grbit          |= $fNotes        << 5;
-        $grbit          |= $fNoOrient     << 6;
-        $grbit          |= $fUsePage      << 7;
-
-        $numHdr = pack("d", $numHdr);
-        $numFtr = pack("d", $numFtr);
-        if ($this->_byte_order) { // if it's Big Endian
-            $numHdr = strrev($numHdr);
-            $numFtr = strrev($numFtr);
-        }
-
-        $header = pack("vv", $record, $length);
-        $data1  = pack("vvvvvvvv", $iPaperSize,
-                                   $iScale,
-                                   $iPageStart,
-                                   $iFitWidth,
-                                   $iFitHeight,
-                                   $grbit,
-                                   $iRes,
-                                   $iVRes);
-        $data2  = $numHdr.$numFtr;
-        $data3  = pack("v", $iCopies);
-        $this->_prepend($header . $data1 . $data2 . $data3);
-    }
-
-    /**
-    * Store the header caption BIFF record.
-    *
-    * @access private
-    */
-    function _storeHeader()
-    {
-        $record  = 0x0014;               // Record identifier
-
-        $str      = $this->_header;       // header string
-        $cch      = strlen($str);         // Length of header string
-        if ($this->_BIFF_version == 0x0600) {
-            $encoding = 0x0;                  // TODO: Unicode support
-            $length   = 3 + $cch;             // Bytes to follow
-        } else {
-            $length  = 1 + $cch;             // Bytes to follow
-        }
-
-        $header   = pack("vv", $record, $length);
-        if ($this->_BIFF_version == 0x0600) {
-            $data     = pack("vC",  $cch, $encoding);
-        } else {
-            $data      = pack("C",  $cch);
-        }
-
-        $this->_prepend($header.$data.$str);
-    }
-
-    /**
-    * Store the footer caption BIFF record.
-    *
-    * @access private
-    */
-    function _storeFooter()
-    {
-        $record  = 0x0015;               // Record identifier
-
-        $str      = $this->_footer;       // Footer string
-        $cch      = strlen($str);         // Length of footer string
-        if ($this->_BIFF_version == 0x0600) {
-            $encoding = 0x0;                  // TODO: Unicode support
-            $length   = 3 + $cch;             // Bytes to follow
-        } else {
-            $length  = 1 + $cch;
-        }
-
-        $header    = pack("vv", $record, $length);
-        if ($this->_BIFF_version == 0x0600) {
-            $data      = pack("vC",  $cch, $encoding);
-        } else {
-            $data      = pack("C",  $cch);
-        }
-
-        $this->_prepend($header . $data . $str);
-    }
-
-    /**
-    * Store the horizontal centering HCENTER BIFF record.
-    *
-    * @access private
-    */
-    function _storeHcenter()
-    {
-        $record   = 0x0083;              // Record identifier
-        $length   = 0x0002;              // Bytes to follow
-
-        $fHCenter = $this->_hcenter;     // Horizontal centering
-
-        $header    = pack("vv", $record, $length);
-        $data      = pack("v",  $fHCenter);
-
-        $this->_prepend($header.$data);
-    }
-
-    /**
-    * Store the vertical centering VCENTER BIFF record.
-    *
-    * @access private
-    */
-    function _storeVcenter()
-    {
-        $record   = 0x0084;              // Record identifier
-        $length   = 0x0002;              // Bytes to follow
-
-        $fVCenter = $this->_vcenter;     // Horizontal centering
-
-        $header    = pack("vv", $record, $length);
-        $data      = pack("v",  $fVCenter);
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Store the LEFTMARGIN BIFF record.
-    *
-    * @access private
-    */
-    function _storeMarginLeft()
-    {
-        $record  = 0x0026;                   // Record identifier
-        $length  = 0x0008;                   // Bytes to follow
-
-        $margin  = $this->_margin_left;       // Margin in inches
-
-        $header    = pack("vv",  $record, $length);
-        $data      = pack("d",   $margin);
-        if ($this->_byte_order) { // if it's Big Endian
-            $data = strrev($data);
-        }
-
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Store the RIGHTMARGIN BIFF record.
-    *
-    * @access private
-    */
-    function _storeMarginRight()
-    {
-        $record  = 0x0027;                   // Record identifier
-        $length  = 0x0008;                   // Bytes to follow
-
-        $margin  = $this->_margin_right;      // Margin in inches
-
-        $header    = pack("vv",  $record, $length);
-        $data      = pack("d",   $margin);
-        if ($this->_byte_order) { // if it's Big Endian
-            $data = strrev($data);
-        }
-
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Store the TOPMARGIN BIFF record.
-    *
-    * @access private
-    */
-    function _storeMarginTop()
-    {
-        $record  = 0x0028;                   // Record identifier
-        $length  = 0x0008;                   // Bytes to follow
-
-        $margin  = $this->_margin_top;        // Margin in inches
-
-        $header    = pack("vv",  $record, $length);
-        $data      = pack("d",   $margin);
-        if ($this->_byte_order) { // if it's Big Endian
-            $data = strrev($data);
-        }
-
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Store the BOTTOMMARGIN BIFF record.
-    *
-    * @access private
-    */
-    function _storeMarginBottom()
-    {
-        $record  = 0x0029;                   // Record identifier
-        $length  = 0x0008;                   // Bytes to follow
-
-        $margin  = $this->_margin_bottom;     // Margin in inches
-
-        $header    = pack("vv",  $record, $length);
-        $data      = pack("d",   $margin);
-        if ($this->_byte_order) { // if it's Big Endian
-            $data = strrev($data);
-        }
-
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Merges the area given by its arguments.
-    * This is an Excel97/2000 method. It is required to perform more complicated
-    * merging than the normal setAlign('merge').
-    *
-    * @access public
-    * @param integer $first_row First row of the area to merge
-    * @param integer $first_col First column of the area to merge
-    * @param integer $last_row  Last row of the area to merge
-    * @param integer $last_col  Last column of the area to merge
-    */
-    function mergeCells($first_row, $first_col, $last_row, $last_col)
-    {
-        $record  = 0x00E5;                   // Record identifier
-        $length  = 0x000A;                   // Bytes to follow
-        $cref     = 1;                       // Number of refs
-
-        // Swap last row/col for first row/col as necessary
-        if ($first_row > $last_row) {
-            list($first_row, $last_row) = array($last_row, $first_row);
-        }
-
-        if ($first_col > $last_col) {
-            list($first_col, $last_col) = array($last_col, $first_col);
-        }
-
-        $header   = pack("vv",    $record, $length);
-        $data     = pack("vvvvv", $cref, $first_row, $last_row,
-                                  $first_col, $last_col);
-
-        $this->_append($header.$data);
-    }
-
-    /**
-    * Write the PRINTHEADERS BIFF record.
-    *
-    * @access private
-    */
-    function _storePrintHeaders()
-    {
-        $record      = 0x002a;                   // Record identifier
-        $length      = 0x0002;                   // Bytes to follow
-
-        $fPrintRwCol = $this->_print_headers;     // Boolean flag
-
-        $header      = pack("vv", $record, $length);
-        $data        = pack("v", $fPrintRwCol);
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the
-    * GRIDSET record.
-    *
-    * @access private
-    */
-    function _storePrintGridlines()
-    {
-        $record      = 0x002b;                    // Record identifier
-        $length      = 0x0002;                    // Bytes to follow
-
-        $fPrintGrid  = $this->_print_gridlines;    // Boolean flag
-
-        $header      = pack("vv", $record, $length);
-        $data        = pack("v", $fPrintGrid);
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Write the GRIDSET BIFF record. Must be used in conjunction with the
-    * PRINTGRIDLINES record.
-    *
-    * @access private
-    */
-    function _storeGridset()
-    {
-        $record      = 0x0082;                        // Record identifier
-        $length      = 0x0002;                        // Bytes to follow
-
-        $fGridSet    = !($this->_print_gridlines);     // Boolean flag
-
-        $header      = pack("vv",  $record, $length);
-        $data        = pack("v",   $fGridSet);
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Write the GUTS BIFF record. This is used to configure the gutter margins
-    * where Excel outline symbols are displayed. The visibility of the gutters is
-    * controlled by a flag in WSBOOL.
-    *
-    * @see _storeWsbool()
-    * @access private
-    */
-    function _storeGuts()
-    {
-        $record      = 0x0080;   // Record identifier
-        $length      = 0x0008;   // Bytes to follow
-
-        $dxRwGut     = 0x0000;   // Size of row gutter
-        $dxColGut    = 0x0000;   // Size of col gutter
-
-        $row_level   = $this->_outline_row_level;
-        $col_level   = 0;
-
-        // Calculate the maximum column outline level. The equivalent calculation
-        // for the row outline level is carried out in setRow().
-        $colcount = count($this->_colinfo);
-        for ($i = 0; $i < $colcount; $i++) {
-           // Skip cols without outline level info.
-           if (count($this->_colinfo[$i]) >= 6) {
-              $col_level = max($this->_colinfo[$i][5], $col_level);
-           }
-        }
-
-        // Set the limits for the outline levels (0 <= x <= 7).
-        $col_level = max(0, min($col_level, 7));
-
-        // The displayed level is one greater than the max outline levels
-        if ($row_level) {
-            $row_level++;
-        }
-        if ($col_level) {
-            $col_level++;
-        }
-
-        $header = pack("vv",   $record, $length);
-        $data   = pack("vvvv", $dxRwGut, $dxColGut, $row_level, $col_level);
-
-        $this->_prepend($header.$data);
-    }
-
-
-    /**
-    * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction
-    * with the SETUP record.
-    *
-    * @access private
-    */
-    function _storeWsbool()
-    {
-        $record      = 0x0081;   // Record identifier
-        $length      = 0x0002;   // Bytes to follow
-        $grbit       = 0x0000;
-
-        // The only option that is of interest is the flag for fit to page. So we
-        // set all the options in one go.
-        //
-        /*if ($this->_fit_page) {
-            $grbit = 0x05c1;
-        } else {
-            $grbit = 0x04c1;
-        }*/
-        // Set the option flags
-        $grbit |= 0x0001;                           // Auto page breaks visible
-        if ($this->_outline_style) {
-            $grbit |= 0x0020; // Auto outline styles
-        }
-        if ($this->_outline_below) {
-            $grbit |= 0x0040; // Outline summary below
-        }
-        if ($this->_outline_right) {
-            $grbit |= 0x0080; // Outline summary right
-        }
-        if ($this->_fit_page) {
-            $grbit |= 0x0100; // Page setup fit to page
-        }
-        if ($this->_outline_on) {
-            $grbit |= 0x0400; // Outline symbols displayed
-        }
-
-        $header = pack("vv", $record, $length);
-        $data   = pack("v",  $grbit);
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Write the HORIZONTALPAGEBREAKS BIFF record.
-    *
-    * @access private
-    */
-    function _storeHbreak()
-    {
-        // Return if the user hasn't specified pagebreaks
-        if (empty($this->_hbreaks)) {
-            return;
-        }
-
-        // Sort and filter array of page breaks
-        $breaks = $this->_hbreaks;
-        sort($breaks, SORT_NUMERIC);
-        if ($breaks[0] == 0) { // don't use first break if it's 0
-            array_shift($breaks);
-        }
-
-        $record  = 0x001b;               // Record identifier
-        $cbrk    = count($breaks);       // Number of page breaks
-        if ($this->_BIFF_version == 0x0600) {
-            $length  = 2 + 6*$cbrk;      // Bytes to follow
-        } else {
-            $length  = 2 + 2*$cbrk;      // Bytes to follow
-        }
-
-        $header  = pack("vv", $record, $length);
-        $data    = pack("v",  $cbrk);
-
-        // Append each page break
-        foreach ($breaks as $break) {
-            if ($this->_BIFF_version == 0x0600) {
-                $data .= pack("vvv", $break, 0x0000, 0x00ff);
-            } else {
-                $data .= pack("v", $break);
-            }
-        }
-
-        $this->_prepend($header.$data);
-    }
-
-
-    /**
-    * Write the VERTICALPAGEBREAKS BIFF record.
-    *
-    * @access private
-    */
-    function _storeVbreak()
-    {
-        // Return if the user hasn't specified pagebreaks
-        if (empty($this->_vbreaks)) {
-            return;
-        }
-
-        // 1000 vertical pagebreaks appears to be an internal Excel 5 limit.
-        // It is slightly higher in Excel 97/200, approx. 1026
-        $breaks = array_slice($this->_vbreaks,0,1000);
-
-        // Sort and filter array of page breaks
-        sort($breaks, SORT_NUMERIC);
-        if ($breaks[0] == 0) { // don't use first break if it's 0
-            array_shift($breaks);
-        }
-
-        $record  = 0x001a;               // Record identifier
-        $cbrk    = count($breaks);       // Number of page breaks
-        if ($this->_BIFF_version == 0x0600) {
-            $length  = 2 + 6*$cbrk;      // Bytes to follow
-        } else {
-            $length  = 2 + 2*$cbrk;      // Bytes to follow
-        }
-
-        $header  = pack("vv",  $record, $length);
-        $data    = pack("v",   $cbrk);
-
-        // Append each page break
-        foreach ($breaks as $break) {
-            if ($this->_BIFF_version == 0x0600) {
-                $data .= pack("vvv", $break, 0x0000, 0xffff);
-            } else {
-                $data .= pack("v", $break);
-            }
-        }
-
-        $this->_prepend($header . $data);
-    }
-
-    /**
-    * Set the Biff PROTECT record to indicate that the worksheet is protected.
-    *
-    * @access private
-    */
-    function _storeProtect()
-    {
-        // Exit unless sheet protection has been specified
-        if ($this->_protect == 0) {
-            return;
-        }
-
-        $record      = 0x0012;             // Record identifier
-        $length      = 0x0002;             // Bytes to follow
-
-        $fLock       = $this->_protect;    // Worksheet is protected
-
-        $header      = pack("vv", $record, $length);
-        $data        = pack("v",  $fLock);
-
-        $this->_prepend($header.$data);
-    }
-
-    /**
-    * Write the worksheet PASSWORD record.
-    *
-    * @access private
-    */
-    function _storePassword()
-    {
-        // Exit unless sheet protection and password have been specified
-        if (($this->_protect == 0) || (!isset($this->_password))) {
-            return;
-        }
-
-        $record      = 0x0013;               // Record identifier
-        $length      = 0x0002;               // Bytes to follow
-
-        $wPassword   = $this->_password;     // Encoded password
-
-        $header      = pack("vv", $record, $length);
-        $data        = pack("v",  $wPassword);
-
-        $this->_prepend($header . $data);
-    }
-
-
-    /**
-    * Insert a 24bit bitmap image in a worksheet.
-    *
-    * @access public
-    * @param integer $row     The row we are going to insert the bitmap into
-    * @param integer $col     The column we are going to insert the bitmap into
-    * @param string  $bitmap  The bitmap filename
-    * @param integer $x       The horizontal position (offset) of the image inside the cell.
-    * @param integer $y       The vertical position (offset) of the image inside the cell.
-    * @param integer $scale_x The horizontal scale
-    * @param integer $scale_y The vertical scale
-    */
-    function insertBitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1)
-    {
-        $bitmap_array = $this->_processBitmap($bitmap);
-        if ($this->isError($bitmap_array)) {
-            $this->writeString($row, $col, $bitmap_array->getMessage());
-            return;
-        }
-        list($width, $height, $size, $data) = $bitmap_array; //$this->_processBitmap($bitmap);
-
-        // Scale the frame of the image.
-        $width  *= $scale_x;
-        $height *= $scale_y;
-
-        // Calculate the vertices of the image and write the OBJ record
-        $this->_positionImage($col, $row, $x, $y, $width, $height);
-
-        // Write the IMDATA record to store the bitmap data
-        $record      = 0x007f;
-        $length      = 8 + $size;
-        $cf          = 0x09;
-        $env         = 0x01;
-        $lcb         = $size;
-
-        $header      = pack("vvvvV", $record, $length, $cf, $env, $lcb);
-        $this->_append($header.$data);
-    }
-
-    /**
-    * Calculate the vertices that define the position of the image as required by
-    * the OBJ record.
-    *
-    *         +------------+------------+
-    *         |     A      |      B     |
-    *   +-----+------------+------------+
-    *   |     |(x1,y1)     |            |
-    *   |  1  |(A1)._______|______      |
-    *   |     |    |              |     |
-    *   |     |    |              |     |
-    *   +-----+----|    BITMAP    |-----+
-    *   |     |    |              |     |
-    *   |  2  |    |______________.     |
-    *   |     |            |        (B2)|
-    *   |     |            |     (x2,y2)|
-    *   +---- +------------+------------+
-    *
-    * Example of a bitmap that covers some of the area from cell A1 to cell B2.
-    *
-    * Based on the width and height of the bitmap we need to calculate 8 vars:
-    *     $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2.
-    * The width and height of the cells are also variable and have to be taken into
-    * account.
-    * The values of $col_start and $row_start are passed in from the calling
-    * function. The values of $col_end and $row_end are calculated by subtracting
-    * the width and height of the bitmap from the width and height of the
-    * underlying cells.
-    * The vertices are expressed as a percentage of the underlying cell width as
-    * follows (rhs values are in pixels):
-    *
-    *       x1 = X / W *1024
-    *       y1 = Y / H *256
-    *       x2 = (X-1) / W *1024
-    *       y2 = (Y-1) / H *256
-    *
-    *       Where:  X is distance from the left side of the underlying cell
-    *               Y is distance from the top of the underlying cell
-    *               W is the width of the cell
-    *               H is the height of the cell
-    *
-    * @access private
-    * @note  the SDK incorrectly states that the height should be expressed as a
-    *        percentage of 1024.
-    * @param integer $col_start Col containing upper left corner of object
-    * @param integer $row_start Row containing top left corner of object
-    * @param integer $x1        Distance to left side of object
-    * @param integer $y1        Distance to top of object
-    * @param integer $width     Width of image frame
-    * @param integer $height    Height of image frame
-    */
-    function _positionImage($col_start, $row_start, $x1, $y1, $width, $height)
-    {
-        // Initialise end cell to the same as the start cell
-        $col_end    = $col_start;  // Col containing lower right corner of object
-        $row_end    = $row_start;  // Row containing bottom right corner of object
-
-        // Zero the specified offset if greater than the cell dimensions
-        if ($x1 >= $this->_sizeCol($col_start)) {
-            $x1 = 0;
-        }
-        if ($y1 >= $this->_sizeRow($row_start)) {
-            $y1 = 0;
-        }
-
-        $width      = $width  + $x1 -1;
-        $height     = $height + $y1 -1;
-
-        // Subtract the underlying cell widths to find the end cell of the image
-        while ($width >= $this->_sizeCol($col_end)) {
-            $width -= $this->_sizeCol($col_end);
-            $col_end++;
-        }
-
-        // Subtract the underlying cell heights to find the end cell of the image
-        while ($height >= $this->_sizeRow($row_end)) {
-            $height -= $this->_sizeRow($row_end);
-            $row_end++;
-        }
-
-        // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
-        // with zero eight or width.
-        //
-        if ($this->_sizeCol($col_start) == 0) {
-            return;
-        }
-        if ($this->_sizeCol($col_end)   == 0) {
-            return;
-        }
-        if ($this->_sizeRow($row_start) == 0) {
-            return;
-        }
-        if ($this->_sizeRow($row_end)   == 0) {
-            return;
-        }
-
-        // Convert the pixel values to the percentage value expected by Excel
-        $x1 = $x1     / $this->_sizeCol($col_start)   * 1024;
-        $y1 = $y1     / $this->_sizeRow($row_start)   *  256;
-        $x2 = $width  / $this->_sizeCol($col_end)     * 1024; // Distance to right side of object
-        $y2 = $height / $this->_sizeRow($row_end)     *  256; // Distance to bottom of object
-
-        $this->_storeObjPicture($col_start, $x1,
-                                 $row_start, $y1,
-                                 $col_end, $x2,
-                                 $row_end, $y2);
-    }
-
-    /**
-    * Convert the width of a cell from user's units to pixels. By interpolation
-    * the relationship is: y = 7x +5. If the width hasn't been set by the user we
-    * use the default value. If the col is hidden we use a value of zero.
-    *
-    * @access private
-    * @param integer $col The column
-    * @return integer The width in pixels
-    */
-    function _sizeCol($col)
-    {
-        // Look up the cell value to see if it has been changed
-        if (isset($this->col_sizes[$col])) {
-            if ($this->col_sizes[$col] == 0) {
-                return(0);
-            } else {
-                return(floor(7 * $this->col_sizes[$col] + 5));
-            }
-        } else {
-            return(64);
-        }
-    }
-
-    /**
-    * Convert the height of a cell from user's units to pixels. By interpolation
-    * the relationship is: y = 4/3x. If the height hasn't been set by the user we
-    * use the default value. If the row is hidden we use a value of zero. (Not
-    * possible to hide row yet).
-    *
-    * @access private
-    * @param integer $row The row
-    * @return integer The width in pixels
-    */
-    function _sizeRow($row)
-    {
-        // Look up the cell value to see if it has been changed
-        if (isset($this->_row_sizes[$row])) {
-            if ($this->_row_sizes[$row] == 0) {
-                return(0);
-            } else {
-                return(floor(4/3 * $this->_row_sizes[$row]));
-            }
-        } else {
-            return(17);
-        }
-    }
-
-    /**
-    * Store the OBJ record that precedes an IMDATA record. This could be generalise
-    * to support other Excel objects.
-    *
-    * @access private
-    * @param integer $colL Column containing upper left corner of object
-    * @param integer $dxL  Distance from left side of cell
-    * @param integer $rwT  Row containing top left corner of object
-    * @param integer $dyT  Distance from top of cell
-    * @param integer $colR Column containing lower right corner of object
-    * @param integer $dxR  Distance from right of cell
-    * @param integer $rwB  Row containing bottom right corner of object
-    * @param integer $dyB  Distance from bottom of cell
-    */
-    function _storeObjPicture($colL,$dxL,$rwT,$dyT,$colR,$dxR,$rwB,$dyB)
-    {
-        $record      = 0x005d;   // Record identifier
-        $length      = 0x003c;   // Bytes to follow
-
-        $cObj        = 0x0001;   // Count of objects in file (set to 1)
-        $OT          = 0x0008;   // Object type. 8 = Picture
-        $id          = 0x0001;   // Object ID
-        $grbit       = 0x0614;   // Option flags
-
-        $cbMacro     = 0x0000;   // Length of FMLA structure
-        $Reserved1   = 0x0000;   // Reserved
-        $Reserved2   = 0x0000;   // Reserved
-
-        $icvBack     = 0x09;     // Background colour
-        $icvFore     = 0x09;     // Foreground colour
-        $fls         = 0x00;     // Fill pattern
-        $fAuto       = 0x00;     // Automatic fill
-        $icv         = 0x08;     // Line colour
-        $lns         = 0xff;     // Line style
-        $lnw         = 0x01;     // Line weight
-        $fAutoB      = 0x00;     // Automatic border
-        $frs         = 0x0000;   // Frame style
-        $cf          = 0x0009;   // Image format, 9 = bitmap
-        $Reserved3   = 0x0000;   // Reserved
-        $cbPictFmla  = 0x0000;   // Length of FMLA structure
-        $Reserved4   = 0x0000;   // Reserved
-        $grbit2      = 0x0001;   // Option flags
-        $Reserved5   = 0x0000;   // Reserved
-
-
-        $header      = pack("vv", $record, $length);
-        $data        = pack("V", $cObj);
-        $data       .= pack("v", $OT);
-        $data       .= pack("v", $id);
-        $data       .= pack("v", $grbit);
-        $data       .= pack("v", $colL);
-        $data       .= pack("v", $dxL);
-        $data       .= pack("v", $rwT);
-        $data       .= pack("v", $dyT);
-        $data       .= pack("v", $colR);
-        $data       .= pack("v", $dxR);
-        $data       .= pack("v", $rwB);
-        $data       .= pack("v", $dyB);
-        $data       .= pack("v", $cbMacro);
-        $data       .= pack("V", $Reserved1);
-        $data       .= pack("v", $Reserved2);
-        $data       .= pack("C", $icvBack);
-        $data       .= pack("C", $icvFore);
-        $data       .= pack("C", $fls);
-        $data       .= pack("C", $fAuto);
-        $data       .= pack("C", $icv);
-        $data       .= pack("C", $lns);
-        $data       .= pack("C", $lnw);
-        $data       .= pack("C", $fAutoB);
-        $data       .= pack("v", $frs);
-        $data       .= pack("V", $cf);
-        $data       .= pack("v", $Reserved3);
-        $data       .= pack("v", $cbPictFmla);
-        $data       .= pack("v", $Reserved4);
-        $data       .= pack("v", $grbit2);
-        $data       .= pack("V", $Reserved5);
-
-        $this->_append($header . $data);
-    }
-
-    /**
-    * Convert a 24 bit bitmap into the modified internal format used by Windows.
-    * This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the
-    * MSDN library.
-    *
-    * @access private
-    * @param string $bitmap The bitmap to process
-    * @return array Array with data and properties of the bitmap
-    */
-    function _processBitmap($bitmap)
-    {
-        // Open file.
-        $bmp_fd = @fopen($bitmap,"rb");
-        if (!$bmp_fd) {
-            $this->raiseError("Couldn't import $bitmap");
-        }
-
-        // Slurp the file into a string.
-        $data = fread($bmp_fd, filesize($bitmap));
-
-        // Check that the file is big enough to be a bitmap.
-        if (strlen($data) <= 0x36) {
-            $this->raiseError("$bitmap doesn't contain enough data.\n");
-        }
-
-        // The first 2 bytes are used to identify the bitmap.
-        $identity = unpack("A2ident", $data);
-        if ($identity['ident'] != "BM") {
-            $this->raiseError("$bitmap doesn't appear to be a valid bitmap image.\n");
-        }
-
-        // Remove bitmap data: ID.
-        $data = substr($data, 2);
-
-        // Read and remove the bitmap size. This is more reliable than reading
-        // the data size at offset 0x22.
-        //
-        $size_array   = unpack("Vsa", substr($data, 0, 4));
-        $size   = $size_array['sa'];
-        $data   = substr($data, 4);
-        $size  -= 0x36; // Subtract size of bitmap header.
-        $size  += 0x0C; // Add size of BIFF header.
-
-        // Remove bitmap data: reserved, offset, header length.
-        $data = substr($data, 12);
-
-        // Read and remove the bitmap width and height. Verify the sizes.
-        $width_and_height = unpack("V2", substr($data, 0, 8));
-        $width  = $width_and_height[1];
-        $height = $width_and_height[2];
-        $data   = substr($data, 8);
-        if ($width > 0xFFFF) {
-            $this->raiseError("$bitmap: largest image width supported is 65k.\n");
-        }
-        if ($height > 0xFFFF) {
-            $this->raiseError("$bitmap: largest image height supported is 65k.\n");
-        }
-
-        // Read and remove the bitmap planes and bpp data. Verify them.
-        $planes_and_bitcount = unpack("v2", substr($data, 0, 4));
-        $data = substr($data, 4);
-        if ($planes_and_bitcount[2] != 24) { // Bitcount
-            $this->raiseError("$bitmap isn't a 24bit true color bitmap.\n");
-        }
-        if ($planes_and_bitcount[1] != 1) {
-            $this->raiseError("$bitmap: only 1 plane supported in bitmap image.\n");
-        }
-
-        // Read and remove the bitmap compression. Verify compression.
-        $compression = unpack("Vcomp", substr($data, 0, 4));
-        $data = substr($data, 4);
-
-        //$compression = 0;
-        if ($compression['comp'] != 0) {
-            $this->raiseError("$bitmap: compression not supported in bitmap image.\n");
-        }
-
-        // Remove bitmap data: data size, hres, vres, colours, imp. colours.
-        $data = substr($data, 20);
-
-        // Add the BITMAPCOREHEADER data
-        $header  = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18);
-        $data    = $header . $data;
-
-        return (array($width, $height, $size, $data));
-    }
-
-    /**
-    * Store the window zoom factor. This should be a reduced fraction but for
-    * simplicity we will store all fractions with a numerator of 100.
-    *
-    * @access private
-    */
-    function _storeZoom()
-    {
-        // If scale is 100 we don't need to write a record
-        if ($this->_zoom == 100) {
-            return;
-        }
-
-        $record      = 0x00A0;               // Record identifier
-        $length      = 0x0004;               // Bytes to follow
-
-        $header      = pack("vv", $record, $length);
-        $data        = pack("vv", $this->_zoom, 100);
-        $this->_append($header . $data);
-    }
-
-    /**
-    * FIXME: add comments
-    */
-    function setValidation($row1, $col1, $row2, $col2, &$validator)
-    {
-        $this->_dv[] = $validator->_getData() .
-                       pack("vvvvv", 1, $row1, $row2, $col1, $col2);
-    }
-
-    /**
-    * Store the DVAL and DV records.
-    *
-    * @access private
-    */
-    function _storeDataValidity()
-    {
-        $record      = 0x01b2;      // Record identifier
-        $length      = 0x0012;      // Bytes to follow
-
-        $grbit       = 0x0002;      // Prompt box at cell, no cached validity data at DV records
-        $horPos      = 0x00000000;  // Horizontal position of prompt box, if fixed position
-        $verPos      = 0x00000000;  // Vertical position of prompt box, if fixed position
-        $objId       = 0xffffffff;  // Object identifier of drop down arrow object, or -1 if not visible
-
-        $header      = pack('vv', $record, $length);
-        $data        = pack('vVVVV', $grbit, $horPos, $verPos, $objId,
-                                     count($this->_dv));
-        $this->_append($header.$data);
-
-        $record = 0x01be;              // Record identifier
-        foreach ($this->_dv as $dv) {
-            $length = strlen($dv);      // Bytes to follow
-            $header = pack("vv", $record, $length);
-            $this->_append($header . $dv);
-        }
-    }
-}
-?>

+ 0 - 6
main/inc/lib/pear/Spreadsheet_Excel_Writer/Writer/index.html

@@ -1,6 +0,0 @@
-<html>
-<head>
-</head>
-<body>
-</body>
-</html>

+ 0 - 6
main/inc/lib/pear/Spreadsheet_Excel_Writer/index.html

@@ -1,6 +0,0 @@
-<html>
-<head>
-</head>
-<body>
-</body>
-</html>

+ 426 - 17
main/inc/lib/sessionmanager.lib.php

@@ -1,4 +1,3 @@
-
 <?php
 /* For licensing terms, see /license.txt */
 
@@ -26,7 +25,7 @@ class SessionManager
 
     /**
      * Fetches a session from the database
-     * @param   int  $id   Session Id
+     * @param  int $id Session Id
      *
      * @return  array   Session details
      */
@@ -263,9 +262,10 @@ class SessionManager
 
     /**
      * @param string $where_condition
+     *
      * @return mixed
      */
-    public static function get_count_admin($where_condition = null)
+    public static function get_count_admin($where_condition = '')
     {
         $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
         $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
@@ -276,7 +276,7 @@ class SessionManager
         $where = 'WHERE 1=1 ';
         $user_id = api_get_user_id();
 
-        $extraJoin = null;
+        $extraJoin = '';
 
         if (api_is_session_admin() &&
             api_get_setting('allow_session_admins_to_manage_all_sessions') == 'false'
@@ -380,8 +380,8 @@ class SessionManager
 
     /**
      * Gets the admin session list callback of the session/session_list.php page
-     * @param array order and limit keys
-     * @param boolean Whether to get all the results or only the count
+     * @param array $options order and limit keys
+     * @param boolean $get_count Whether to get all the results or only the count
      * @return mixed Integer for number of rows, or array of results
      * @assert (array(),true) !== false
      */
@@ -2408,11 +2408,16 @@ class SessionManager
             $msg = get_lang('StartDateShouldBeBeforeEndDate');
             return $msg;
         }
+
         $access_url_id = api_get_current_access_url_id();
-        $sql = "INSERT INTO $tbl_session_category (name, date_start, date_end, access_url_id)
-        		VALUES('" . Database::escape_string($name) . "','$date_start','$date_end', '$access_url_id')";
-        Database::query($sql);
-        $id_session = Database::insert_id();
+        $params = [
+            'name' => $name,
+            'date_start' => $date_start,
+            'date_end' => $date_end,
+            'access_url_id' => $access_url_id
+        ];
+        $id_session = Database::insert($tbl_session_category, $params);
+
         // Add event to system log
         $user_id = api_get_user_id();
         Event::addEvent(
@@ -5421,11 +5426,11 @@ class SessionManager
         }
 
         $sql1 = "UPDATE $table SET position = '".intval($nextOrder)."'
-                 WHERE session_id = $sessionId AND c_id =  '".$thisCourseCode."'";
+                 WHERE session_id = $sessionId AND c_id =  $thisCourseCode";
         Database::query($sql1);
 
         $sql2 = "UPDATE $table SET position = '".intval($thisOrder)."'
-                 WHERE session_id = $sessionId AND c_id =  '".$nextId."'";
+                 WHERE session_id = $sessionId AND c_id = $nextId";
         Database::query($sql2);
 
         return true;
@@ -6004,11 +6009,11 @@ class SessionManager
                         u.username AS coach_username,
                         u.firstname AS coach_firstname,
                         u.lastname AS coach_lastname
-                    FROM $courseTable c
-                    INNER JOIN $sessionCourseUserTable scu ON c.id = scu.c_id
-                    INNER JOIN $userTable u ON scu.user_id = u.user_id
-                    WHERE scu.status = 2 AND scu.session_id IN $sessionIdsString
-                    ORDER BY scu.session_id ASC ";
+                        FROM $courseTable c
+                        INNER JOIN $sessionCourseUserTable scu ON c.id = scu.c_id
+                        INNER JOIN $userTable u ON scu.user_id = u.user_id
+                        WHERE scu.status = 2 AND scu.session_id IN $sessionIdsString
+                        ORDER BY scu.session_id ASC ";
                 $res = Database::query($sql);
                 $sessionCourseList = Database::store_result($res, 'ASSOC');
                 // Check if course list had result
@@ -7125,4 +7130,408 @@ class SessionManager
 
         return false;
     }
+
+    /**
+     * Return an associative array 'id_course' => [id_session1, id_session2...]
+     * where course id_course is in sessions id_session1, id_session2
+     * for course where user is coach
+     * i.e. coach for the course or
+     * main coach for a session the course is in
+     * for a session category (or woth no session category if empty)
+     *
+     * @param $userId
+     *
+     * @return array
+     */
+    public static function getSessionCourseForUser($userId)
+    {
+        // list of COURSES where user is COURSE session coach
+        $listCourseCourseCoachSession = self::getCoursesForCourseSessionCoach($userId);
+
+        // list of courses where user is MAIN session coach
+        $listCourseMainCoachSession = self::getCoursesForMainSessionCoach($userId);
+
+        // merge these 2 array
+        $listResCourseSession = $listCourseCourseCoachSession;
+        foreach ($listCourseMainCoachSession as $courseId2 => $listSessionId2) {
+            if (isset($listResCourseSession[$courseId2])) {
+                // if sessionId array exists for this course
+                // same courseId, merge the list of session
+                foreach ($listCourseMainCoachSession[$courseId2] as $i => $sessionId2) {
+                    if (!in_array($sessionId2, $listResCourseSession[$courseId2])) {
+                        $listResCourseSession[$courseId2][] = $sessionId2;
+                    }
+                }
+            } else {
+                $listResCourseSession[$courseId2] = $listSessionId2;
+            }
+        }
+
+        return $listResCourseSession;
+    }
+
+    /**
+     * Return an associative array 'id_course' => [id_session1, id_session2...]
+     * where course id_course is in sessions id_session1, id_session2
+     * @param $userId
+     *
+     * @return array
+     */
+    public static function getCoursesForCourseSessionCoach($userId)
+    {
+        $listResCourseSession = array();
+        $tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
+        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+
+        $sql = "SELECT session_id, c_id, c.id
+                FROM $tblSessionRelCourseRelUser srcru
+                LEFT JOIN $tblCourse c
+                ON c.id = srcru.c_id
+                WHERE
+                    srcru.user_id =".intval($userId)." AND
+                    srcru.status = 2";
+
+        $res = Database::query($sql);
+
+        while ($data = Database::fetch_assoc($res)) {
+            if (self::isSessionDateOkForCoach($data['session_id'])) {
+                if (!isset($listResCourseSession[$data['id']])) {
+                    $listResCourseSession[$data['id']] = array();
+                }
+                $listResCourseSession[$data['id']][] = $data['session_id'];
+            }
+        }
+
+        return $listResCourseSession;
+    }
+
+    /**
+     * Return true if coach is allowed to access this session
+     * @param int $sessionId
+     * @return bool
+     */
+    public static function isSessionDateOkForCoach($sessionId)
+    {
+        return api_get_session_visibility($sessionId);
+
+        $listSessionInfo = api_get_session_info($sessionId);
+        $dateStart = $listSessionInfo['date_start'];
+        $dateEnd = $listSessionInfo['date_end'];
+        $nbDaysAccessBeforeBeginning = $listSessionInfo['nb_days_access_before_beginning'];
+        $nbDaysAccessAfterEnd = $listSessionInfo['nb_days_access_after_end'];
+
+        // no start date
+        if ($dateStart == '0000-00-00') {
+            return true;
+        }
+
+        $now = time();
+
+        $dateStartForCoach = api_strtotime($dateStart.' 00:00:00') - ($nbDaysAccessBeforeBeginning * 86400);
+        $dateEndForCoach = api_strtotime($dateEnd.' 00:00:00') + ($nbDaysAccessAfterEnd * 86400);
+
+        if ($dateEnd == '0000-00-00') {
+            // start date but no end date
+            if ($dateStartForCoach <= $now) {
+                return true;
+            }
+        } else {
+            // start date and end date
+            if ($dateStartForCoach <= $now && $now <= $dateEndForCoach) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Return an associative array 'id_course' => [id_session1, id_session2...]
+     * where course id_course is in sessions id_session1, id_session2
+     * @param $userId
+     *
+     * @return array
+     */
+    public static function getCoursesForMainSessionCoach($userId)
+    {
+        $listResCourseSession = array();
+        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
+
+        // list of SESSION where user is session coach
+        $sql = "SELECT id FROM $tblSession
+                WHERE id_coach = ".intval($userId);
+        $res = Database::query($sql);
+
+        while ($data = Database::fetch_assoc($res)) {
+            $sessionId = $data['id'];
+            $listCoursesInSession = self::getCoursesInSession($sessionId);
+            foreach ($listCoursesInSession as $i => $courseId) {
+                if (self::isSessionDateOkForCoach($sessionId)) {
+                    if (!isset($listResCourseSession[$courseId])) {
+                        $listResCourseSession[$courseId] = array();
+                    }
+                    $listResCourseSession[$courseId][] = $sessionId;
+                }
+            }
+        }
+
+        return $listResCourseSession;
+    }
+
+    /**
+     * Return an array of course_id used in session $sessionId
+     * @param $sessionId
+     *
+     * @return array
+     */
+    public static function getCoursesInSession($sessionId)
+    {
+        $listResultsCourseId = array();
+        $tblSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
+        $tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
+
+        // list of course in this session
+        $sql = "SELECT session_id, c.id
+                FROM $tblSessionRelCourse src
+                LEFT JOIN $tblCourse c
+                ON c.id = src.c_id
+                WHERE session_id = ".intval($sessionId);
+        $res = Database::query($sql);
+        while ($data = Database::fetch_assoc($res)) {
+            $listResultsCourseId[] = $data['id'];
+        }
+
+        return $listResultsCourseId;
+    }
+
+    /**
+     * Return an array of courses in session for user
+     * and for each courses the list of session that use this course for user
+     *
+     * [0] => array
+     *      userCatId
+     *      userCatTitle
+     *      courseInUserCatList
+     *          [0] => array
+     *              courseId
+     *              title
+     *              courseCode
+     *              sessionCatList
+     *                  [0] => array
+     *                      catSessionId
+     *                      catSessionName
+     *                      sessionList
+     *                          [0] => array
+     *                              sessionId
+     *                              sessionName
+     *
+     * @param $userId
+     * @return array
+     *
+     */
+    public static function getNamedSessionCourseForCoach($userId)
+    {
+        $listResults = array();
+        $listCourseSession = self::getSessionCourseForUser($userId);
+        foreach ($listCourseSession as $courseId => $listSessionId) {
+            // Course info
+            $courseInfo = api_get_course_info_by_id($courseId);
+            $listOneCourse = array();
+            $listOneCourse['courseId'] = $courseId;
+            $listOneCourse['title'] = $courseInfo['title'];
+            $listOneCourse['courseCode'] = $courseInfo['code'];
+            $listOneCourse['sessionCatList'] = array();
+            $listCat = array();
+            foreach ($listSessionId as $i => $sessionId) {
+                // here we got all session for this course
+                // lets check there session categories
+                $sessionInfo = SessionManager::fetch($sessionId);
+                $catId = $sessionInfo['session_category_id'];
+                if (!isset($listCat[$catId])) {
+                    $listCatInfo = self::get_session_category($catId);
+                    $listCat[$catId] = array();
+                    $listCat[$catId]['catSessionId'] = $catId;
+                    $listCat[$catId]['catSessionName'] = $listCatInfo['name'];
+                    $listCat[$catId]['sessionList'] = array();
+                }
+                $listSessionInfo = SessionManager::fetch($sessionId);
+                $listSessionIdName = array(
+                    "sessionId" => $sessionId,
+                    "sessionName" => $listSessionInfo['name'],
+                );
+                $listCat[$catId]['sessionList'][] = $listSessionIdName;
+            }
+            // sort $listCat by catSessionName
+            usort($listCat, 'self::compareBySessionName');
+            // in each catSession sort sessionList by sessionName
+            foreach($listCat as $i => $listCatSessionInfo) {
+                $listSessionList = $listCatSessionInfo['sessionList'];
+                usort($listSessionList, 'self::compareCatSessionInfo');
+                $listCat[$i]['sessionList'] = $listSessionList;
+            }
+
+            $listOneCourse['sessionCatList'] = $listCat;
+
+            // user course category
+            list($userCatId, $userCatTitle) = CourseManager::getUserCourseCategoryForCourse(
+                $userId,
+                $courseId
+            );
+
+            $userCatId = intval($userCatId);
+            $listResults[$userCatId]['courseInUserCategoryId'] =  $userCatId;
+            $listResults[$userCatId]['courseInUserCategoryTitle'] =  $userCatTitle;
+            $listResults[$userCatId]['courseInUserCatList'][] = $listOneCourse;
+        }
+
+        // sort by user course cat
+        uasort($listResults, 'self::compareByUserCourseCat');
+
+        // sort by course title
+        foreach ($listResults as $userCourseCatId => $tabCoursesInCat) {
+            $courseInUserCatList = $tabCoursesInCat['courseInUserCatList'];
+            uasort($courseInUserCatList, 'self::compareByCourse');
+            $listResults[$userCourseCatId]['courseInUserCatList'] = $courseInUserCatList;
+        }
+
+        return $listResults;
+    }
+
+    /**
+     * @param array $listA
+     * @param array $listB
+     * @return int
+     */
+    private static function compareCatSessionInfo($listA, $listB)
+    {
+        if ($listA['sessionName'] == $listB['sessionName']) {
+            return 0;
+        } else if($listA['sessionName'] > $listB['sessionName']) {
+            return 1;
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * @param array $listA
+     * @param array $listB
+     * @return int
+     */
+    private static function compareBySessionName($listA, $listB)
+    {
+        if ($listB['catSessionName'] == '') {
+            return -1;
+        } else if ($listA['catSessionName'] == '') {
+            return 1;
+        } else if ($listA['catSessionName'] == $listB['catSessionName']) {
+            return 0;
+        } else if($listA['catSessionName'] > $listB['catSessionName']) {
+            return 1;
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * @param array $listA
+     * @param array $listB
+     * @return int
+     */
+    private static function compareByUserCourseCat($listA, $listB)
+    {
+        if ($listA['courseInUserCategoryTitle'] == $listB['courseInUserCategoryTitle']) {
+            return 0;
+        } else if($listA['courseInUserCategoryTitle'] > $listB['courseInUserCategoryTitle']) {
+            return 1;
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * @param array $listA
+     * @param array $listB
+     * @return int
+     */
+    private static function compareByCourse($listA, $listB)
+    {
+        if ($listA['title'] == $listB['title']) {
+            return 0;
+        } else if($listA['title'] > $listB['title']) {
+            return 1;
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * Return HTML code for displaying session_course_for_coach
+     * @param $userId
+     * @return string
+     */
+    public static function getHtmlNamedSessionCourseForCoach($userId)
+    {
+        $htmlRes = '';
+
+        $listInfo = self::getNamedSessionCourseForCoach($userId);
+        foreach($listInfo as $i => $listCoursesInfo) {
+            $courseCode = $listCoursesInfo['courseCode'];
+            $courseTitle = $listCoursesInfo['title'];
+            $listParamsCourse = array();
+            $listParamsCourse['icon'] = '<div style="float:left">
+                <input style="border:none;" type="button" onclick="$(\'#course-'.$courseCode.'\').toggle(\'fast\')" value="+" /></div>'.
+                Display::return_icon('blackboard.png', $listCoursesInfo['title'], array(), ICON_SIZE_LARGE);
+            $listParamsCourse['link'] = '';
+            $listParamsCourse['title'] = Display::tag(
+                'a',
+                $listCoursesInfo['title'],
+                array('href' => $listParamsCourse['link'])
+            );
+            $htmlCourse = '<div class="well" style="border-color:#27587D">'.
+                CourseManager::course_item_html($listParamsCourse, true);
+            // for each category of session
+            $htmlCatSessions = '';
+            foreach ($listCoursesInfo['sessionCatList'] as $j => $listCatSessionsInfo) {
+                // we got an array of session categories
+                $catSessionId = $listCoursesInfo['sessionCatList'][$j]['catSessionId'];
+                $catSessionName = $listCoursesInfo['sessionCatList'][$j]['catSessionName'];
+
+                $listParamsCatSession['icon'] = Display::return_icon('folder_blue.png', $catSessionName, array(), ICON_SIZE_LARGE);
+                $listParamsCatSession['link'] = '';
+                $listParamsCatSession['title'] = $catSessionName;
+
+                $marginShift = 20;
+                if ($catSessionName != '') {
+                    $htmlCatSessions .= '<div style="margin-left:'.$marginShift.'px;">' .
+                        CourseManager::course_item_html($listParamsCatSession, true) . '</div>';
+                    $marginShift = 40;
+                }
+
+                // for each sessions
+                $listCatSessionSessionList = $listCoursesInfo['sessionCatList'][$j]['sessionList'];
+                $htmlSession = '';
+                foreach ($listCatSessionSessionList as $k => $listSessionInfo) {
+                    // we got an array of session info
+                    $sessionId = $listSessionInfo['sessionId'];
+                    $sessionName = $listSessionInfo['sessionName'];
+
+                    $listParamsSession['icon'] = Display::return_icon('blackboard_blue.png', $sessionName, array(), ICON_SIZE_LARGE);
+                    $listParamsSession['link'] = '';
+                    $linkToCourseSession = api_get_path(WEB_PATH).'courses/'.$courseCode.'/?id_session='.$sessionId;
+                    $listParamsSession['title'] = $sessionName.'<div style="font-weight:normal; font-style:italic">
+                    <a href="'.$linkToCourseSession.'">
+                    '.get_lang('GoToCourseInsideSession').'</a></div>';
+                    $htmlSession .= '<div style="margin-left:'.$marginShift.'px;">'.
+                        CourseManager::course_item_html($listParamsSession, true).'</div>';
+                }
+                $htmlCatSessions .= $htmlSession;
+            }
+            $htmlRes .= $htmlCourse.'<div style="display:none" id="course-'.$courseCode.'">'.$htmlCatSessions.'</div></div>';
+        }
+
+        return $htmlRes;
+    }
+
+
 }

+ 5 - 1
main/inc/lib/social.lib.php

@@ -1498,7 +1498,11 @@ class SocialManager extends UserManager
             return '';
         }
 
-        $socialAvatarBlock = SocialManager::show_social_avatar_block($groupBlock, $groupId, $userId);
+        $socialAvatarBlock = SocialManager::show_social_avatar_block(
+            $groupBlock,
+            $groupId,
+            $userId
+        );
 
         $profileEditionLink = null;
         if (api_get_user_id() == $userId) {

+ 50 - 42
main/inc/lib/system_announcements.lib.php

@@ -353,63 +353,71 @@ class SystemAnnouncementManager
 		$start = api_get_utc_datetime($date_start);
         $end = api_get_utc_datetime($date_end);
 
-		$title = Database::escape_string($title);
-		$content = Database::escape_string($content);
-
 		//Fixing urls that are sent by email
 		$content = str_replace('src=\"/home/', 'src=\"'.api_get_path(WEB_PATH).'home/', $content);
 		$content = str_replace('file=/home/', 'file='.api_get_path(WEB_PATH).'home/', $content);
 
-		$langsql = is_null($lang) ? 'NULL' : "'".Database::escape_string($lang)."'";
+        $lang = is_null($lang) ? 'NULL' : $lang;
 
 		$current_access_url_id = 1;
 		if (api_is_multiple_url_enabled()) {
 			$current_access_url_id = api_get_current_access_url_id();
 		}
 
-		$sql = "INSERT INTO ".$db_table." (title,content,date_start,date_end,visible_teacher,visible_student,visible_guest, lang, access_url_id)
-				VALUES ('".$title."','".$content."','".$start."','".$end."','".$visible_teacher."','".$visible_student."','".$visible_guest."',".$langsql.", ".$current_access_url_id.")";
+		$params = [
+			'title' => $title,
+			'content' => $content,
+			'date_start' => $start,
+			'date_end' => $end,
+			'visible_teacher' => $visible_teacher,
+			'visible_student' => $visible_student,
+			'visible_guest' => $visible_guest,
+			'lang' => $lang,
+			'access_url_id' => $current_access_url_id,
+		];
+
+		$resultId = Database::insert($db_table, $params);
+
+		if ($resultId) {
+
+			if ($sendEmailTest) {
+				SystemAnnouncementManager::send_system_announcement_by_email(
+					$title,
+					$content,
+					$visible_teacher,
+					$visible_student,
+					$lang,
+					true
+				);
+			} else {
+				if ($send_mail == 1) {
+					SystemAnnouncementManager::send_system_announcement_by_email(
+						$title,
+						$content,
+						$visible_teacher,
+						$visible_student,
+						$lang
+					);
+				}
+			}
 
-        if ($sendEmailTest) {
-            SystemAnnouncementManager::send_system_announcement_by_email(
-                $title,
-                $content,
-                $visible_teacher,
-                $visible_student,
-                $lang,
-                true
-            );
-        } else {
-            if ($send_mail == 1) {
-                SystemAnnouncementManager::send_system_announcement_by_email(
-                    $title,
-                    $content,
-                    $visible_teacher,
-                    $visible_student,
-                    $lang
-                );
-            }
-        }
+			if ($add_to_calendar) {
+				$agenda = new Agenda();
+				$agenda->setType('admin');
+				$agenda->addEvent(
+					$date_start,
+					$date_end,
+					false,
+					$title,
+					$original_content
+				);
+			}
 
-		$res = Database::query($sql);
-		if ($res === false) {
-			return false;
-		}
+			return $resultId;
 
-		$id = null;
-		if ($add_to_calendar) {
-			$agenda = new Agenda();
-			$agenda->setType('admin');
-			$id = $agenda->addEvent(
-				$date_start,
-				$date_end,
-				false,
-				$title,
-				$original_content
-			);
 		}
 
-		return $id;
+		return false;
 	}
 
     /**

+ 4 - 2
main/inc/lib/template.lib.php

@@ -610,8 +610,10 @@ class Template
             'chosen/chosen.jquery.min.js',
         );
 
-        if (api_is_global_chat_enabled()) {
-            //Do not include the global chat in LP
+        $viewBySession = api_get_configuration_value('my_courses_view_by_session');
+
+        if (api_is_global_chat_enabled() || $viewBySession) {
+            // Do not include the global chat in LP
             if ($this->show_learnpath == false &&
                 $this->show_footer == true &&
                 $this->hide_global_chat == false

+ 1 - 1
main/inc/lib/text.lib.php

@@ -732,7 +732,7 @@ function _text_parse_tool($input) {
  * @author Patrick Cool <patrick.cool@UGent.be> Ghent University
  */
 function latex_gif_renderer($latex_code) {
-    global $_course;
+    $_course = api_get_course_info();
 
     // Setting the paths and filenames
     $mimetex_path = api_get_path(LIBRARY_PATH).'mimetex/';

+ 49 - 25
main/inc/lib/thematic.lib.php

@@ -276,7 +276,7 @@ class Thematic
      */
     public function thematic_save()
     {
-        global $_course;
+        $_course = api_get_course_info();
         // definition database table
         $tbl_thematic = Database::get_course_table(TABLE_THEMATIC);
 
@@ -292,32 +292,53 @@ class Thematic
 
         if (empty($id)) {
             // insert
-            $sql = "INSERT INTO $tbl_thematic (c_id, title, content, active, display_order, session_id)
-					VALUES ($this->course_int_id, '$title', '$content', 1, ".(intval($max_thematic_item)+1).", $session_id) ";
-            $result = Database::query($sql);
-            $last_id = Database::insert_id();
+            $params = [
+                'c_id' => $this->course_int_id,
+                'title' => $title,
+                'content' => $content,
+                'active' => 1,
+                'display_order' => intval($max_thematic_item) + 1,
+                'session_id' => $session_id
+            ];
+            $last_id = Database::insert($tbl_thematic, $params);
             if ($last_id) {
                 $sql = "UPDATE $tbl_thematic SET id = iid WHERE iid = $last_id";
                 Database::query($sql);
-                api_item_property_update($_course, 'thematic', $last_id,"ThematicAdded", $user_id);
-            }
-        } else {
-            // update
-            $sql = "UPDATE $tbl_thematic SET title = '$title', content = '$content', session_id = $session_id
-                    WHERE id = $id AND c_id = {$this->course_int_id}";
-            $result = Database::query($sql);
-            $last_id = $id;
-            if (Database::affected_rows($result)) {
-                // save inside item property table
                 api_item_property_update(
                     $_course,
                     'thematic',
                     $last_id,
-                    "ThematicUpdated",
+                    "ThematicAdded",
                     $user_id
                 );
             }
+        } else {
+            // Update
+            $params = [
+                'title' => $title,
+                'content' => $content,
+                'session_id' => $session_id
+            ];
+
+            Database::update(
+                $tbl_thematic,
+                $params,
+                ['id  = ? AND c_id = ?' => [$id, $this->course_int_id]]
+            );
+
+            $last_id = $id;
+
+            // save inside item property table
+            api_item_property_update(
+                $_course,
+                'thematic',
+                $last_id,
+                "ThematicUpdated",
+                $user_id
+            );
+
         }
+
         return $last_id;
     }
 
@@ -328,7 +349,7 @@ class Thematic
      */
     public function thematic_destroy($thematic_id)
     {
-        global $_course;
+        $_course = api_get_course_info();
         $tbl_thematic = Database::get_course_table(TABLE_THEMATIC);
         $affected_rows = 0;
         $user_id = api_get_user_id();
@@ -655,7 +676,7 @@ class Thematic
      */
     public function thematic_advance_save()
     {
-        global $_course;
+        $_course = api_get_course_info();
 
         // definition database table
         $tbl_thematic_advance = Database::get_course_table(TABLE_THEMATIC_ADVANCE);
@@ -703,7 +724,7 @@ class Thematic
      */
     public function thematic_advance_destroy($thematic_advance_id)
     {
-        global $_course;
+        $_course = api_get_course_info();
         $course_id = api_get_course_int_id();
 
         // definition database table
@@ -815,7 +836,7 @@ class Thematic
      */
     public function thematic_plan_save()
     {
-        global $_course;
+        $_course = api_get_course_info();
         // definition database table
         $tbl_thematic_plan = Database::get_course_table(TABLE_THEMATIC_PLAN);
 
@@ -902,7 +923,7 @@ class Thematic
      */
     public function thematic_plan_destroy($thematic_id, $description_type)
     {
-        global $_course;
+        $_course = api_get_course_info();
         // definition database table
         $tbl_thematic_plan = Database::get_course_table(TABLE_THEMATIC_PLAN);
 
@@ -919,7 +940,10 @@ class Thematic
 
         // delete
         $sql = "DELETE FROM $tbl_thematic_plan
-                WHERE c_id = $course_id AND thematic_id = $thematic_id AND description_type = $description_type ";
+                WHERE
+                    c_id = $course_id AND
+                    thematic_id = $thematic_id AND
+                    description_type = $description_type ";
         $result = Database::query($sql);
         $affected_rows = Database::affected_rows($result);
         if ($affected_rows) {
@@ -975,10 +999,10 @@ class Thematic
      */
     public function update_done_thematic_advances($thematic_advance_id)
     {
-        global $_course;
-        $thematic_data         = $this->get_thematic_list(null, api_get_course_id());
+        $_course = api_get_course_info();
+        $thematic_data = $this->get_thematic_list(null, api_get_course_id());
         $thematic_advance_data = $this->get_thematic_advance_list(null, api_get_course_id(), true);
-        $tbl_thematic_advance  = Database::get_course_table(TABLE_THEMATIC_ADVANCE);
+        $tbl_thematic_advance = Database::get_course_table(TABLE_THEMATIC_ADVANCE);
 
         $affected_rows = 0;
         $user_id       = api_get_user_id();

+ 367 - 0
main/inc/lib/userportal.lib.php

@@ -6,6 +6,9 @@
  */
 class IndexManager
 {
+    const VIEW_BY_DEFAULT = 0;
+    const VIEW_BY_SESSION = 1;
+
     // An instance of the template engine
     public $tpl = false;
     public $name = '';
@@ -1330,4 +1333,368 @@ class IndexManager
         return CourseManager::return_hot_courses(30, 6);
     }
 
+    /**
+     * UserPortal view for session, return the HTLK of the course list
+     * @param $user_id
+     * @return string
+     */
+    public function returnCoursesAndSessionsViewBySession($user_id)
+    {
+        $sessionCount = 0;
+        $courseCount = 0;
+
+        $load_history = (isset($_GET['history']) && intval($_GET['history']) == 1) ? true : false;
+
+        if ($load_history) {
+            //Load sessions in category in *history*
+            $session_categories = UserManager::get_sessions_by_category($user_id, true);
+        } else {
+            //Load sessions in category
+            $session_categories = UserManager::get_sessions_by_category($user_id, false);
+        }
+
+        $html = '';
+
+        //Showing history title
+        if ($load_history) {
+            $html .= Display::page_subheader(get_lang('HistoryTrainingSession'));
+            if (empty($session_categories)) {
+                $html .=  get_lang('YouDoNotHaveAnySessionInItsHistory');
+            }
+        }
+
+        $special_courses = '';
+
+        $loadDirs = $this->load_directories_preview;
+
+        // If we're not in the history view...
+        $listCoursesInfo = array();
+        if (!isset($_GET['history'])) {
+            // Display special courses
+            $specialCoursesResult = CourseManager::display_special_courses(
+                $user_id,
+                $loadDirs
+            );
+            $specialCourses = $specialCoursesResult['html'];
+
+            // Display courses
+            // [code=>xxx, real_id=>000]
+            $listCourses = CourseManager::get_courses_list_by_user_id($user_id, false);
+            foreach ($listCourses as $i => $listCourseCodeId) {
+                list($userCategoryId, $userCatTitle) = CourseManager::getUserCourseCategoryForCourse(
+                    $user_id,
+                    $listCourseCodeId['real_id']
+                );
+                $listCourse = api_get_course_info_by_id($listCourseCodeId['real_id']);
+                $listCoursesInfo[] = array(
+                    'code' => $listCourseCodeId['code'],
+                    'id' => $listCourseCodeId['real_id'],
+                    'title' => $listCourse['title'],
+                    'userCatId' => $userCategoryId,
+                    'userCatTitle' => $userCatTitle
+                );
+                $courseCount++;
+            }
+            usort($listCoursesInfo, 'self::compareByCourse');
+        }
+
+        if (is_array($session_categories)) {
+            // all courses that are in a session
+            $listCoursesInSession = SessionManager::getNamedSessionCourseForCoach($user_id);
+        }
+
+        // we got all courses
+        // for each user category, sorted alphabetically, display courses
+        $listUserCategories = CourseManager::get_user_course_categories($user_id);
+        $listCoursesAlreadyDisplayed = array();
+        uasort($listUserCategories, "self::compareListUserCategory");
+        $listUserCategories[0] = '';
+
+        $html = '<div class="session-view-block">';
+
+        foreach ($listUserCategories as $userCategoryId => $userCatTitle) {
+            // add user category
+            $userCategoryHtml = '';
+            if ($userCategoryId != 0) {
+                $userCategoryHtml = '<div class="session-view-well ">';
+            }
+            $userCategoryHtml .= self::getHtmlForUserCategory($userCategoryId, $userCatTitle);
+
+            // look for course in this userCat in session courses : $listCoursesInSession
+            $htmlCategory = '';
+            if (isset($listCoursesInSession[$userCategoryId])) {
+                // list of courses in this user cat
+                foreach ($listCoursesInSession[$userCategoryId]['courseInUserCatList'] as $i => $listCourse) {
+                    // add course
+                    $listCoursesAlreadyDisplayed[$listCourse['courseId']] = 1;
+                    if ($userCategoryId == 0) {
+                        $htmlCategory .= '<div class="session-view-well session-view-row well" >';
+                    } else {
+                        $htmlCategory .= '<div class="session-view-row" >';
+                    }
+
+                    $htmlCategory .= self::getHtmlForCourse(
+                        $listCourse['courseId'],
+                        $listCourse['title'],
+                        $listCourse['courseCode'],
+                        $userCategoryId,
+                        1,
+                        $loadDirs
+                    );
+                    // list of session category
+                    $htmlSessionCategory = '<div class="session-view-row" style="display:none;" id="courseblock-'.$listCourse['courseId'].'">';
+                    foreach ($listCourse['sessionCatList'] as $j => $listCategorySession) {
+                        // add session category
+                        $htmlSessionCategory .= self::getHtmlSessionCategory(
+                            $listCategorySession['catSessionId'],
+                            $listCategorySession['catSessionName']
+                        );
+                        // list of session
+                        $htmlSession = '';    // start
+                        foreach ($listCategorySession['sessionList'] as $k => $listSession) {
+                            // add session
+                            $htmlSession .= '<div class="session-view-row">';
+                            $htmlSession .= self::getHtmlForSession(
+                                $listSession['sessionId'],
+                                $listSession['sessionName'],
+                                $listCategorySession['catSessionId'],
+                                $listCourse['courseCode']
+                            );
+                            $htmlSession .= '</div>';
+                            $sessionCount++;
+                        }
+                        $htmlSession .= ''; // end session block
+                        $htmlSessionCategory .= $htmlSession;
+                    }
+                    $htmlSessionCategory .= '</div>'; // end session cat block
+                    $htmlCategory .=  $htmlSessionCategory .'</div>' ;
+                    $htmlCategory .= '';   // end course block
+                }
+                $userCategoryHtml .= $htmlCategory;
+            }
+
+            // look for courses in this userCat in not in session courses : $listCoursesInfo
+            // if course not already added
+            $htmlCategory = '';
+            foreach ($listCoursesInfo as $i => $listCourse) {
+                if ($listCourse['userCatId'] == $userCategoryId && !isset($listCoursesAlreadyDisplayed[$listCourse['id']])) {
+                    if ($userCategoryId != 0) {
+                        $htmlCategory .= '<div class="session-view-row" >';
+                    } else {
+                        $htmlCategory .= '<div class="session-view-well well">';
+                    }
+                    $htmlCategory .= self::getHtmlForCourse(
+                        $listCourse['id'],
+                        $listCourse['title'],
+                        $listCourse['code'],
+                        $userCategoryId,
+                        0,
+                        $loadDirs
+                    );
+                    $htmlCategory .= '</div>';
+                }
+            }
+            $htmlCategory .= '';
+            $userCategoryHtml .= $htmlCategory;   // end user cat block
+            if ($userCategoryId != 0) {
+                $userCategoryHtml .= '</div>';
+            }
+            $html .= $userCategoryHtml;   //
+        }
+        $html .= '</div>';
+
+        return [
+            'html' => $html.$specialCourses,
+            'session_count' => $sessionCount,
+            'course_count' => $courseCount
+        ];
+    }
+
+    /**
+     * Return HTML code for personnal user course category
+     * @param $id
+     * @param $title
+     * @return string
+     */
+    private static function getHtmlForUserCategory($id, $title)
+    {
+        if ($id == 0) {
+            return '';
+        }
+        $icon = Display::return_icon(
+            'folder_yellow.png',
+            $title,
+            array('class' => 'sessionView', 'width' => 24),
+            ICON_SIZE_LARGE
+        );
+        return "<div class='session-view-user-category'>$icon<span>$title</span></div>";
+    }
+
+    /**
+     * return HTML code for course display in session view
+     * @param $id
+     * @param $title
+     * @param $code
+     * @param $userCategoryId
+     * @param bool $displayButton
+     * @param $loadDirs
+     * @return string
+     */
+    private static function getHtmlForCourse($id, $title, $code, $userCategoryId, $displayButton = false, $loadDirs)
+    {
+        $class = 'session-view-lvl-6';
+        if ($userCategoryId != 0 && !$displayButton) {
+            $class = 'session-view-lvl-7';
+        }
+
+        $class2 = 'session-view-lvl-6';
+        if ($displayButton || $userCategoryId != 0) {
+            $class2 = 'session-view-lvl-7';
+        }
+
+        $button = '';
+        if ($displayButton) {
+            $button = '<input id="session-view-button-'.intval($id).'" class="session-view-button btn btn-default" type="button" onclick="hideUnhide(\'courseblock-'.intval($id).'\', \'session-view-button-'.intval($id).'\', \'+\', \'-\')" value="+" />';
+        }
+
+        $icon = Display::return_icon(
+            'blackboard.png',
+            $title,
+            array('class' => 'sessionView', 'width' => 24),
+            ICON_SIZE_LARGE
+        );
+
+        $courseLink = api_get_path(WEB_COURSE_PATH).$code.'/index.php?id_session=0';
+
+        // get html course params
+        // ['right_actions'] ['teachers'] ['notifications']
+        $tabParams = CourseManager::getCourseParamsForDisplay($id, $loadDirs);
+        // teacher list
+        if (!empty($tabParams['teachers'])) {
+            $teachers = '<p class="'.$class2.' view-by-session-teachers">'.$tabParams['teachers'].'</p>';
+        }
+
+        // notification
+        if (!empty($tabParams['right_actions'])) {
+            $rightActions = '<div class="view-by-session-right-actions">'.$tabParams['right_actions'].'</div>';
+        }
+
+        return "<div>
+                    $button
+                    <span class='$class'>$icon
+                    <a class='sessionView' href='$courseLink'>$title</a>
+                    </span>".$tabParams['notifications']."$rightActions
+                </div>
+                $teachers";
+    }
+
+    /**
+     * return HTML code for session category
+     * @param $id
+     * @param $title
+     * @return string
+     */
+    private static function getHtmlSessionCategory($id, $title)
+    {
+        if ($id == 0) {
+            return '';
+        }
+
+        $icon = Display::return_icon(
+            'folder_blue.png',
+            $title,
+            array('class' => 'sessionView', 'width' => 24),
+            ICON_SIZE_LARGE
+        );
+
+        return "<div class='session-view-session-category'>
+                <span class='session-view-lvl-2'>
+                    $icon
+                    <span>$title</span>
+                </span>
+                </div>";
+    }
+
+    /**
+     * return HTML code for session
+     * @param $id
+     * @param $title
+     * @param $categotySessionId
+     * @param $courseCode
+     * @return string
+     */
+    private static function getHtmlForSession($id, $title, $categotySessionId, $courseCode)
+    {
+        $html = '';
+
+        if ($categotySessionId == 0) {
+            $class1 = 'session-view-lvl-2';    // session
+            $class2 = 'session-view-lvl-4';    // got to course in session link
+        } else {
+            $class1 = 'session-view-lvl-3';    // session
+            $class2 = 'session-view-lvl-5';    // got to course in session link
+        }
+
+        $icon = Display::return_icon(
+            'blackboard_blue.png',
+            $title,
+            array('class' => 'sessionView', 'width' => 24),
+            ICON_SIZE_LARGE
+        );
+        $courseLink = api_get_path(WEB_COURSE_PATH).$courseCode.'/index.php?id_session='.intval($id);
+
+        $html .= "<span class='$class1 session-view-session'>$icon$title</span>";
+        $html .= '<div class="'.$class2.' session-view-session-go-to-course-in-session">
+                <a class="" href="'.$courseLink.'">'.get_lang('GoToCourseInsideSession').'</a></div>';
+
+        return '<div>'.$html.'</div>';
+    }
+
+    /**
+     * @param $listA
+     * @param $listB
+     * @return int
+     */
+    private static function compareByCourse($listA, $listB)
+    {
+        if ($listA['userCatTitle'] == $listB['userCatTitle']) {
+            if ($listA['title'] == $listB['title']) {
+                return 0;
+            } else if($listA['title'] > $listB['title']) {
+                return 1;
+            } else {
+                return -1;
+            }
+        } else if ($listA['userCatTitle'] > $listB['userCatTitle']) {
+            return 1;
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * @param $listA
+     * @param $listB
+     * @return int
+     */
+    public static function compareListUserCategory($listA, $listB)
+    {
+        if ($listA['title'] == $listB['title']) {
+            return 0;
+        } else if($listA['title'] > $listB['title']) {
+            return 1;
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * @param $view
+     * @param $userId
+     */
+    public static function setDefaultMyCourseView($view, $userId)
+    {
+        setcookie('defaultMyCourseView'.$userId, $view);
+    }
+
 }

+ 2 - 0
main/install/configuration.dist.php

@@ -228,3 +228,5 @@ $_configuration['system_stable'] = NEW_VERSION_STABLE;
 //$_configuration['user_reset_password'] = false;
 // password token expired
 //$_configuration['user_reset_password_token_limit'] = 3600;
+// Show Default view and Session view link in My Courses tab
+//$_configuration['my_courses_view_by_session'] = false;

+ 1 - 1
main/lang/dutch/trad4all.inc.php

@@ -5503,4 +5503,4 @@ $List = "Lijst";
 $CourseDescriptions = "Cursus beschrijvingen";
 $GlossaryTermUpdated = "Termen aangepast";
 $DeleteAllGlossaryTerms = "Verwijder alle termen";
-?>
+?>

+ 2 - 2
main/lang/english/trad4all.inc.php

@@ -5832,7 +5832,7 @@ $Item = "Item";
 $ConfigureDashboardPlugin = "Configure Dashboard Plugin";
 $EditBlocks = "Edit blocks";
 $Never = "Never";
-$YourAccountIsActiveYouCanLoginAndCheckYourCourses = "Dear user, 
+$YourAccountIsActiveYouCanLoginAndCheckYourCourses = "Dear user,
 
 Your account has now been activated on the platform. Please login and enjoy your courses.";
 $SessionFields = "Session fields";
@@ -7472,4 +7472,4 @@ $AddAttachment = "Add attachment";
 $FieldTypeOnlyLetters = "Text only letters";
 $FieldTypeAlphanumeric = "Text only alphanumeric characters";
 $OnlyLetters = "Only letters";
-?>
+?>

+ 17 - 26
main/mySpace/current_courses.php

@@ -4,15 +4,11 @@
  * Report for current courses followed by the user
  * @package chamilo.reporting
  */
-/**
- * Code
- */
+
 $cidReset = true;
 require_once '../inc/global.inc.php';
 $this_section = SECTION_TRACKING;
 
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer.php';
-
 $filename = 'reporting.xls';
 
 if (!api_is_allowed_to_create_course()) {
@@ -38,9 +34,7 @@ if (!empty($my_courses)) {
 		}
 
 		$teachers = CourseManager::get_teacher_list_from_course_code($course_code);
-        $teacher_list =  array();
-
-		//$teacher_list = array($course_info['titular']);
+		$teacher_list =  array();
 
 		if (!empty($teachers)) {
 			foreach($teachers as $teacher) {
@@ -66,7 +60,10 @@ if (!empty($my_courses)) {
 		$t_lpi 	= Database :: get_course_table(TABLE_LP_ITEM);
 		$t_news = Database :: get_course_table(TABLE_ANNOUNCEMENT);
 
-		$total_tools_list = Tracking::get_tools_most_used_by_course($course_id, $session_id);
+		$total_tools_list = Tracking::get_tools_most_used_by_course(
+			$course_id,
+			$session_id
+		);
 
 		$total_tools = 0;
 		foreach($total_tools_list as $tool) {
@@ -192,7 +189,6 @@ if (!empty($my_courses)) {
 	}
 }
 
-
 $headers = array(
 	get_lang('LearningPath'),
 	get_lang('Teachers'),
@@ -215,32 +211,32 @@ $headers = array(
 
 if (isset($_GET['export'])) {
 	global $charset;
-	$workbook = new Spreadsheet_Excel_Writer();
-	$workbook ->setTempDir(api_get_path(SYS_ARCHIVE_PATH));
-	$workbook->send($filename);
-	$workbook->setVersion(8); // BIFF8
-	$worksheet =& $workbook->addWorksheet('Report');
-	//$worksheet->setInputEncoding(api_get_system_encoding());
-	$worksheet->setInputEncoding($charset);
+    $spreadsheet = new PHPExcel();
+    $spreadsheet->setActiveSheetIndex(0);
+    $worksheet = $spreadsheet->getActiveSheet();
 
 	$line = 0;
 	$column = 0; //skip the first column (row titles)
 
-	foreach($headers as $header) {
-		$worksheet->write($line,$column, $header);
+	foreach ($headers as $header) {
+		$worksheet->SetCellValueByColumnAndRow($line, $column, $header);
 		$column++;
 	}
 	$line++;
 	foreach ($array as $row) {
 		$column = 0;
 		foreach ($row as $item) {
-			$worksheet->write($line,$column,html_entity_decode(strip_tags($item)));
+			$worksheet->SetCellValueByColumnAndRow($line, $column, html_entity_decode(strip_tags($item)));
 			$column++;
 		}
 		$line++;
 	}
 	$line++;
-	$workbook->close();
+
+    $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
+    $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
+    $writer->save($file);
+    DocumentManager::file_send_for_download($file, true, $filename);
 	exit;
 }
 
@@ -248,10 +244,6 @@ $interbreadcrumb[] = array ('url' => 'index.php', 'name' => get_lang('MySpace'))
 
 Display::display_header(get_lang('CurrentCourses'));
 
-if (!class_exists('HTML_Table')) {
-	require_once api_get_path(LIBRARY_PATH).'pear/HTML/Table.php';
-}
-
 $table = new HTML_Table(array('class' => 'data_table'));
 $row = 0;
 $column = 0;
@@ -272,7 +264,6 @@ foreach ($array as $row_table) {
 	$row++;
 }
 
-
 echo '<div class="actions">';
 echo '<a href="'.api_get_path(WEB_CODE_PATH).'mySpace">'.Display::return_icon('back.png', get_lang('Back'), array(), 32).'</a>';
 echo '<a href="'.api_get_path(WEB_CODE_PATH).'mySpace/current_courses.php?export=1">'.Display::return_icon('export_excel.png', get_lang('CurrentCoursesReport'), array(), 32).'</a> ';

+ 10 - 7
main/newscorm/learnpath.class.php

@@ -492,6 +492,7 @@ class learnpath
             error_log('New LP - In learnpath::add_item(' . $parent . ',' . $previous . ',' . $type . ',' . $id . ',' . $title . ')', 0);
         }
         $tbl_lp_item = Database :: get_course_table(TABLE_LP_ITEM);
+        $_course = api_get_course_info();
         $parent = intval($parent);
         $previous = intval($previous);
         $id = intval($id);
@@ -633,7 +634,6 @@ class learnpath
             // Upload audio.
             if (!empty($_FILES['mp3']['name'])) {
                 // Create the audio folder if it does not exist yet.
-                global $_course;
                 $filepath = api_get_path(SYS_COURSE_PATH) . $_course['path'] . '/document/';
                 if (!is_dir($filepath . 'audio')) {
                     mkdir($filepath . 'audio', api_get_permissions_for_new_directories());
@@ -1246,6 +1246,8 @@ class learnpath
         $url = ''
     ) {
         $course_id = api_get_course_int_id();
+        $_course = api_get_course_info();
+
         if ($this->debug > 0) {
             error_log('New LP - In learnpath::edit_item()', 0);
         }
@@ -1263,7 +1265,6 @@ class learnpath
         $audio_update_sql = '';
         if (is_array($audio) && !empty ($audio['tmp_name']) && $audio['error'] === 0) {
             // Create the audio folder if it does not exist yet.
-            global $_course;
             $filepath = api_get_path(SYS_COURSE_PATH) . $_course['path'] . '/document/';
             if (!is_dir($filepath . 'audio')) {
                 mkdir($filepath . 'audio', api_get_permissions_for_new_directories());
@@ -2172,7 +2173,7 @@ class learnpath
     public function get_mediaplayer($autostart = 'true')
     {
         $course_id = api_get_course_int_id();
-        global $_course;
+        $_course = api_get_course_info();
         $tbl_lp_item 		= Database :: get_course_table(TABLE_LP_ITEM);
         $tbl_lp_item_view 	= Database :: get_course_table(TABLE_LP_ITEM_VIEW);
 
@@ -5441,10 +5442,12 @@ class learnpath
     public function overview()
     {
         $is_allowed_to_edit = api_is_allowed_to_edit(null,true);
+        $_course = api_get_course_info();
+
         if ($this->debug > 0) {
             error_log('New LP - In learnpath::overview()', 0);
         }
-        global $_course;
+
         $_SESSION['gradebook'] = isset($_GET['gradebook']) ? Security :: remove_XSS($_GET['gradebook']) : null;
         $return = '';
 
@@ -6265,7 +6268,7 @@ class learnpath
      */
     public function display_document($id, $show_title = false, $iframe = true, $edit_link = false)
     {
-        global $_course; // It is temporary.
+        $_course = api_get_course_info();
         $course_id = api_get_course_int_id();
         $return = '';
         $tbl_doc = Database :: get_course_table(TABLE_DOCUMENT);
@@ -7302,8 +7305,9 @@ class learnpath
     public function display_document_form($action = 'add', $id = 0, $extra_info = 'new')
     {
         $course_id = api_get_course_int_id();
+        $_course = api_get_course_info();
         $tbl_lp_item = Database :: get_course_table(TABLE_LP_ITEM);
-        $tbl_doc 	 = Database :: get_course_table(TABLE_DOCUMENT);
+        $tbl_doc = Database :: get_course_table(TABLE_DOCUMENT);
 
         $no_display_edit_textarea = false;
 
@@ -7556,7 +7560,6 @@ class learnpath
                                 $relative_path = $relative_path . '/';
                             }
                         } else {
-                            global $_course;
                             $result = $this->generate_lp_folder($_course);
                             $relative_path = api_substr($result['dir'], 1, strlen($result['dir']));
                             $relative_prefix = '../../';

+ 1 - 1
main/newscorm/lp_admin_view.php

@@ -34,6 +34,7 @@ $tbl_lp_item = Database::get_course_table(TABLE_LP_ITEM);
 $isStudentView  = isset($_REQUEST['isStudentView']) ? (int) $_REQUEST['isStudentView'] : null;
 $learnpath_id   = (int) $_REQUEST['lp_id'];
 $submit			= isset($_POST['submit_button']) ? $_POST['submit_button'] : null;
+$_course = api_get_course_info();
 
 /* MAIN CODE */
 
@@ -110,7 +111,6 @@ if (isset($_POST['save_audio'])) {
             $lp_item_id = str_ireplace('mp3file', '', $key);
 
             // Create the audio folder if it does not exist yet.
-            global $_course;
             DocumentManager::createDefaultAudioFolder($_course);
 
             // Check if file already exits into document/audio/

+ 4 - 3
main/newscorm/openoffice_document.class.php

@@ -44,7 +44,7 @@ abstract class OpenofficeDocument extends learnpath
      */
     public function convert_document($file, $action_after_conversion = 'make_lp')
     {
-        global $_course;
+        $_course = api_get_course_info();
         $this->file_name = pathinfo($file['name'], PATHINFO_FILENAME);
         // Create the directory
         $result = $this->generate_lp_folder($_course, $this->file_name);
@@ -219,8 +219,9 @@ abstract class OpenofficeDocument extends learnpath
      * @param string $convertedTitle
      * @return bool
      */
-    function convertCopyDocument($originalPath, $convertedPath, $convertedTitle){
-        global $_course;
+    function convertCopyDocument($originalPath, $convertedPath, $convertedTitle)
+    {
+        $_course = api_get_course_info();
         $ids = array();
         $originalPathInfo = pathinfo($originalPath);
         $convertedPathInfo = pathinfo($convertedPath);

+ 4 - 3
main/newscorm/openoffice_presentation.class.php

@@ -33,7 +33,7 @@ class OpenofficePresentation extends OpenofficeDocument
 
     public function make_lp($files = array())
     {
-        global $_course;
+        $_course = api_get_course_info();
         $previous = 0;
         $i = 0;
 
@@ -217,9 +217,10 @@ class OpenofficePresentation extends OpenofficeDocument
 
     function add_docs_to_visio($files = array())
     {
-        global $_course;
+        $_course = api_get_course_info();
         foreach ($files as $file) {
-            list($slide_name,$file_name) = explode('||',$file); // '||' is used as separator between slide name (with accents) and file name (without accents).
+            // '||' is used as separator between slide name (with accents) and file name (without accents).
+            list($slide_name,$file_name) = explode('||',$file);
             $slide_name = api_htmlentities($slide_name, ENT_COMPAT, $this->original_charset);
             $slide_name = str_replace('&rsquo;', '\'', $slide_name);
             $slide_name = api_convert_encoding($slide_name, api_get_system_encoding(), $this->original_charset);

+ 49 - 16
main/newscorm/openoffice_text.class.php

@@ -44,9 +44,9 @@ class OpenofficeText extends OpenofficeDocument {
      * @param	array	The files that will compose the generated learning path. Unused so far.
      * @return	boolean	False if file does not exit. Nothing otherwise.
      */
-    function make_lp($files = array()) {
-
-        global $_course;
+    function make_lp($files = array())
+    {
+        $_course = api_get_course_info();
         // We get a content where ||page_break|| indicates where the page is broken.
         if (!file_exists($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html')) { return false; }
         $content = file_get_contents($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html');
@@ -77,7 +77,7 @@ class OpenofficeText extends OpenofficeDocument {
         $my_style = api_get_setting('stylesheets');
         if (empty($my_style)) { $my_style = 'chamilo'; }
         $style_to_import = "<style type=\"text/css\">\r\n";
-        $style_to_import .= '@import "'.api_get_path(WEB_CODE_PATH).'css/'.$my_style.'/default.css";'."\n";        
+        $style_to_import .= '@import "'.api_get_path(WEB_CODE_PATH).'css/'.$my_style.'/default.css";'."\n";
         $style_to_import .= "</style>\r\n";
         $header = preg_replace("|</head>|i", "\r\n$style_to_import\r\n\\0", $header);
 
@@ -98,10 +98,9 @@ class OpenofficeText extends OpenofficeDocument {
      * @param	string	Content
      * @return	void
      */
-    function dealPerChapter($header, $content) {
-
-        global $_course;
-
+    function dealPerChapter($header, $content)
+    {
+        $_course = api_get_course_info();
         $content = str_replace('||page_break||', '', $content);
 
         // Get all the h1.
@@ -116,14 +115,12 @@ class OpenofficeText extends OpenofficeDocument {
                 $matches[1][$new_index] = $matches_temp[1][$i];
                 $new_index++;
             }
-
         }
 
         // Add intro item.
         $intro_content = substr($content, 0, strpos($content, $matches[0][0]));
         $items_to_create[get_lang('Introduction')] = $intro_content;
 
-
         for ($i = 0; $i < count($matches[0]); $i++) {
 
             if (empty($matches[1][$i]))
@@ -154,13 +151,31 @@ class OpenofficeText extends OpenofficeDocument {
             if ($document_id){
 
                 // Put the document in item_property update.
-                api_item_property_update($_course, TOOL_DOCUMENT, $document_id, 'DocumentAdded', $_SESSION['_uid'], 0, 0, null, null, api_get_session_id());
+                api_item_property_update(
+                    $_course,
+                    TOOL_DOCUMENT,
+                    $document_id,
+                    'DocumentAdded',
+                    $_SESSION['_uid'],
+                    0,
+                    0,
+                    null,
+                    null,
+                    api_get_session_id()
+                );
 
                 $infos = pathinfo($this->filepath);
                 $slide_name = strip_tags(nl2br($item_title));
                 $slide_name = str_replace(array("\r\n", "\r", "\n"), '', $slide_name);
                 $slide_name = html_entity_decode($slide_name);
-                $previous = learnpath::add_item(0, $previous, 'document', $document_id, $slide_name, '');
+                $previous = learnpath::add_item(
+                    0,
+                    $previous,
+                    'document',
+                    $document_id,
+                    $slide_name,
+                    ''
+                );
                 if ($this->first_item == 0) {
                     $this->first_item = $previous;
                 }
@@ -174,8 +189,9 @@ class OpenofficeText extends OpenofficeDocument {
      * @param	string	Page body
      * @return	void
      */
-    function dealPerPage($header, $body) {
-        global $_course;
+    function dealPerPage($header, $body)
+    {
+        $_course = api_get_course_info();
         // Split document to pages.
         $pages = explode('||page_break||', $body);
 
@@ -192,14 +208,31 @@ class OpenofficeText extends OpenofficeDocument {
             fwrite($handle, $page_content);
             fclose($handle);
 
-            $document_id = add_document($_course, $this->created_dir.$html_file, 'file', filesize($this->base_work_dir.$this->created_dir.$html_file), $html_file);
+            $document_id = add_document(
+                $_course,
+                $this->created_dir.$html_file,
+                'file',
+                filesize($this->base_work_dir.$this->created_dir.$html_file),
+                $html_file
+            );
 
             $slide_name = '';
 
             if ($document_id) {
 
                 // Put the document in item_property update.
-                api_item_property_update($_course, TOOL_DOCUMENT, $document_id, 'DocumentAdded', $_SESSION['_uid'], 0, 0, null, null, api_get_session_id());
+                api_item_property_update(
+                    $_course,
+                    TOOL_DOCUMENT,
+                    $document_id,
+                    'DocumentAdded',
+                    $_SESSION['_uid'],
+                    0,
+                    0,
+                    null,
+                    null,
+                    api_get_session_id()
+                );
 
                 $infos = pathinfo($this->filepath);
                 $slide_name = 'Page '.str_repeat('0', 2 - strlen($key)).$key;

+ 11 - 10
main/newscorm/openoffice_text_document.class.php

@@ -40,9 +40,9 @@ class OpenOfficeTextDocument extends OpenofficeDocument {
      * @param	array	The files that will compose the generated learning path. Unused so far.
      * @return	boolean	False if file does not exit. Nothing otherwise.
      */
-    public function make_lp($files = array()) {
-
-        global $_course;
+    public function make_lp($files = array())
+    {
+        $_course = api_get_course_info();
         // We get a content where ||page_break|| indicates where the page is broken.
         if (!file_exists($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html')) { return false; }
         $content = file_get_contents($this->base_work_dir.'/'.$this->created_dir.'/'.$this->file_name.'.html');
@@ -73,7 +73,7 @@ class OpenOfficeTextDocument extends OpenofficeDocument {
         $my_style = api_get_setting('stylesheets');
         if (empty($my_style)) { $my_style = 'chamilo'; }
         $style_to_import = "<style type=\"text/css\">\r\n";
-        $style_to_import .= '@import "'.api_get_path(WEB_CODE_PATH).'css/'.$my_style.'/default.css";'."\n";        
+        $style_to_import .= '@import "'.api_get_path(WEB_CODE_PATH).'css/'.$my_style.'/default.css";'."\n";
         $style_to_import .= "</style>\r\n";
         $header = preg_replace("|</head>|i", "\r\n$style_to_import\r\n\\0", $header);
 
@@ -94,9 +94,9 @@ class OpenOfficeTextDocument extends OpenofficeDocument {
      * @param	string	Content
      * @return	void
      */
-    function dealPerChapter($header, $content) {
-
-        global $_course;
+    function dealPerChapter($header, $content)
+    {
+        $_course = api_get_course_info();
 
         $content = str_replace('||page_break||', '', $content);
 
@@ -166,8 +166,9 @@ class OpenOfficeTextDocument extends OpenofficeDocument {
      * @param	string	Page body
      * @return	void
      */
-    function dealPerPage($header, $body) {
-        global $_course;
+    function dealPerPage($header, $body)
+    {
+        $_course = api_get_course_info();
         // Split document to pages.
         $pages = explode('||page_break||', $body);
 
@@ -293,7 +294,7 @@ class OpenOfficeTextDocument extends OpenofficeDocument {
             if (!$defined_width) {
 
                 $image_size = api_getimagesize($this->base_work_dir.$this->created_dir.'/'.$image);
-                $img_width  = $image_size['width']; 
+                $img_width  = $image_size['width'];
                 $img_height = $image_size['height'];
 
                 $new_width = $max_width - 10;

+ 23 - 15
main/session/resume_session.php

@@ -122,9 +122,9 @@ $generalCoach = api_get_user_info($sessionInfo['id_coach']);
 $sessionField = new ExtraField('session');
 $extraFieldData = $sessionField->getDataAndFormattedValues($sessionId);
 $multiple_url_is_on = api_get_multiple_access_url();
-$url_list = [];
+$urlList = [];
 if ($multiple_url_is_on) {
-    $url_list = UrlManager::get_access_url_from_session($sessionId);
+    $urlList = UrlManager::get_access_url_from_session($sessionId);
 }
 
 $url = Display::url(
@@ -148,24 +148,24 @@ if ($sessionInfo['nbr_courses'] == 0) {
 } else {
     $count = 0;
     $courseItem = '';
-
+    /** @var \Chamilo\CoreBundle\Entity\Repository\SessionRepository $sessionRepository */
     $sessionRepository = Database::getManager()->getRepository('ChamiloCoreBundle:Session');
     $courses = $sessionRepository->getCoursesOrderedByPosition($session);
 
 	foreach ($courses as $course) {
-                //select the number of users
-                $sql = "SELECT count(*)
+        //select the number of users
+        $sql = "SELECT count(*)
                 FROM $tbl_session_rel_user sru,
                 $tbl_session_rel_course_rel_user srcru
-				WHERE
-				    srcru.user_id = sru.user_id AND
-				    srcru.session_id = sru.session_id AND
-				    srcru.c_id = '".intval($course->getId())."' AND
-				    sru.relation_type <> ".SESSION_RELATION_TYPE_RRHH." AND
-				    srcru.session_id = '".intval($sessionId)."'";
+                WHERE
+                    srcru.user_id = sru.user_id AND
+                    srcru.session_id = sru.session_id AND
+                    srcru.c_id = '".intval($course->getId())."' AND
+                    sru.relation_type <> ".SESSION_RELATION_TYPE_RRHH." AND
+                    srcru.session_id = '".intval($sessionId)."'";
 
 		$rs = Database::query($sql);
-                $numberOfUsers = Database::result($rs, 0, 0);
+        $numberOfUsers = Database::result($rs, 0, 0);
 
 		// Get coachs of the courses in session
 
@@ -181,7 +181,10 @@ if ($sessionInfo['nbr_courses'] == 0) {
 		$coachs = array();
 		if (Database::num_rows($rs) > 0) {
 			while($info_coach = Database::fetch_array($rs)) {
-				$coachs[] = api_get_person_name($info_coach['firstname'], $info_coach['lastname']).' ('.$info_coach['username'].')';
+                $coachs[] = api_get_person_name(
+                        $info_coach['firstname'],
+                        $info_coach['lastname']
+                    ).' ('.$info_coach['username'].')';
 			}
 		} else {
 			$coach = get_lang('None');
@@ -221,9 +224,14 @@ if ($sessionInfo['nbr_courses'] == 0) {
             $downUrl
         );
 
+        if (!SessionManager::orderCourseIsEnabled()) {
+            $orderButtons = '';
+        }
+
         $courseUrl = api_get_course_url($course->getCode(), $sessionId);
 
-		//hide_course_breadcrumb the parameter has been added to hide the name of the course, that appeared in the default $interbreadcrumb
+		// hide_course_breadcrumb the parameter has been added to hide the name
+		// of the course, that appeared in the default $interbreadcrumb
         $courseItem .= '
 		<tr>
 			<td>'.Display::url(
@@ -370,7 +378,7 @@ $tpl->assign('session', $sessionInfo);
 $tpl->assign('session_category', is_null($sessionCategory) ? null : $sessionCategory->getName());
 $tpl->assign('session_dates', SessionManager::parseSessionDates($sessionInfo));
 $tpl->assign('session_visibility', SessionManager::getSessionVisibility($sessionInfo));
-$tpl->assign('url_list', $url_list);
+$tpl->assign('url_list', $urlList);
 $tpl->assign('extra_fields', $extraFieldData);
 $tpl->assign('course_list', $courseListToShow);
 $tpl->assign('user_list', $userListToShow);

+ 30 - 26
main/social/profile.php

@@ -145,7 +145,7 @@ $locale = api_get_language_isocode();
 // Add Jquery scroll pagination plugin
 $htmlHeadXtra[] = api_get_js('jscroll/jquery.jscroll.js');
 // Add Jquery Time ago plugin
-$htmlHeadXtra[] = api_get_js('jquery-timeago/jquery.timeago.js');
+$htmlHeadXtra[] = api_get_asset('jquery-timeago/jquery.timeago.js');
 $timeAgoLocaleDir = $javascriptDir . 'jquery-timeago/locales/jquery.timeago.' . $locale . '.js';
 if (file_exists($timeAgoLocaleDir)) {
     $htmlHeadXtra[] = api_get_js('jquery-timeago/locales/jquery.timeago.' . $locale . '.js');
@@ -255,23 +255,20 @@ foreach ($sessionList as $session) {
 }
 
 // My friends
-$friend_html = SocialManager::listMyFriends($user_id, $link_shared ,$show_full_profile);
+$friend_html = SocialManager::listMyFriends(
+    $user_id,
+    $link_shared,
+    $show_full_profile
+);
 
 $wallSocialAddPost = SocialManager::getWallForm();
 $social_wall_block = $wallSocialAddPost;
 
 // Social Post Wall
-$post_wall = SocialManager::getWallMessagesByUser($my_user_id, $friendId) ;
-
-$social_post_wall_block  = '<div class="panel panel-default social-post">';
-$social_post_wall_block .= '<div class="panel-heading">Mis publicaciones</div>';
-$social_post_wall_block .='<div class="panel-body">';
-if(empty($post_wall)){
-    $social_post_wall_block .= '<p>'.get_lang("NoPosts").'</p>';
-}else{
-    $social_post_wall_block .= $post_wall;
-}
-$social_post_wall_block .= '</div></div>';
+$posts = SocialManager::getWallMessagesByUser($my_user_id, $friendId) ;
+
+$posts = empty($posts) ? '<p>'.get_lang("NoPosts").'</p>' : $posts;
+$social_post_wall_block = Display::panel($posts, get_lang('Posts'));
 
 $socialAutoExtendLink = Display::url(
     get_lang('SeeMore'),
@@ -291,10 +288,6 @@ if ($show_full_profile) {
 
     $extra_information = '';
     if (is_array($extra_user_data) && count($extra_user_data)>0 ) {
-
-        $extra_information .= '<div class="panel panel-default">';
-        $extra_information .= '<div class="panel-heading">'.get_lang('ExtraInformation').'</div>';
-        $extra_information .='<div class="panel-body">';
         $extra_information_value = '';
         $extraField = new ExtraField('user');
         foreach ($extra_user_data as $key => $data) {
@@ -375,19 +368,21 @@ if ($show_full_profile) {
                     break;
                 }
             }
-
         }
+
         // if there are information to show
         if (!empty($extra_information_value)) {
-            $extra_information .= $extra_information_value;
+            $extra_information .= Display::panel(
+                $extra_information_value,
+                get_lang('ExtraInformation')
+            );
         }
-        $extra_information .= '</div></div>'; //social-profile-info
     }
 
     // If there are information to show Block Extra Information
 
     if (!empty($extra_information_value)) {
-        $social_extra_info_block =  $extra_information;
+        $social_extra_info_block = $extra_information;
     }
 
     // MY GROUPS
@@ -398,12 +393,14 @@ if ($show_full_profile) {
     if (is_array($results) && count($results) > 0) {
         $i = 1;
         foreach ($results as $result) {
-            if ($i > $max_numbers_of_group) break;
+            if ($i > $max_numbers_of_group) {
+                break;
+            }
             $id = $result['id'];
             $url_open  = '<a href="group_view.php?id='.$id.'">';
             $url_close = '</a>';
             $icon = '';
-            $name = cut($result['name'],CUT_GROUP_NAME,true);
+            $name = cut($result['name'], CUT_GROUP_NAME, true);
             if ($result['relation_type'] == GROUP_USER_PERMISSION_ADMIN) {
                 $icon = Display::return_icon(
                     'social_group_admin.png',
@@ -425,7 +422,11 @@ if ($show_full_profile) {
             }
             $item_name = $url_open.$name.$icon.$url_close;
             $item_actions = '';
-            $grid_my_groups[]= array($item_name,$url_open.$result['picture'].$url_close, $item_actions);
+            $grid_my_groups[] = array(
+                $item_name,
+                $url_open.$result['picture'].$url_close,
+                $item_actions,
+            );
             $i++;
         }
     }
@@ -439,6 +440,7 @@ if ($show_full_profile) {
         } else {
             $count_groups = count($results);
         }
+
         $my_groups .= '<div class="panel panel-default">';
         $my_groups .= '<div class="panel-heading">'.get_lang('MyGroups').' ('.$count_groups.') </div>';
 
@@ -512,7 +514,9 @@ if ($show_full_profile) {
     }
 
     $count_pending_invitations = 0;
-    if (!isset($_GET['u']) || (isset($_GET['u']) && $_GET['u']==api_get_user_id())) {
+    if (!isset($_GET['u']) ||
+        (isset($_GET['u']) && $_GET['u']==api_get_user_id())
+    ) {
         $pending_invitations = SocialManager::get_list_invitation_of_friends_by_user_id(api_get_user_id());
         $list_get_path_web = SocialManager::get_list_web_path_user_invitation_by_user_id(api_get_user_id());
         $count_pending_invitations = count($pending_invitations);
@@ -560,7 +564,7 @@ if ($show_full_profile) {
             }
         }
 
-        //--Productions
+        // Productions
         $production_list =  UserManager::build_production_list($user_id);
 
         $product_content  = '';

+ 68 - 26
main/survey/survey.lib.php

@@ -2951,24 +2951,19 @@ class SurveyUtil
      */
     static function export_complete_report_xls($survey_data, $filename, $user_id = 0)
     {
-        require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer.php';
-        $workbook = new Spreadsheet_Excel_Writer();
-        $workbook ->setTempDir(api_get_path(SYS_ARCHIVE_PATH));
-        $workbook->send($filename);
-        $workbook->setVersion(8); // BIFF8
-        $worksheet =& $workbook->addWorksheet('Report 1');
-        $worksheet->setInputEncoding(api_get_system_encoding());
+        $spreadsheet = new PHPExcel();
+        $spreadsheet->setActiveSheetIndex(0);
+        $worksheet = $spreadsheet->getActiveSheet();
         $line = 0;
         $column = 1; // Skip the first column (row titles)
 
         // Show extra fields blank space (enough for extra fields on next line)
-        $display_extra_user_fields = false;
         //if (!empty($_REQUEST['fields_filter'])) {
         // Show user fields section with a big th colspan that spans over all fields
         $extra_user_fields = UserManager::get_extra_fields(0, 0, 5, 'ASC', false, true);
         $num = count($extra_user_fields);
         for ($i = 0; $i < $num; $i++) {
-            $worksheet->write($line, $column, '');
+            $worksheet->SetCellValueByColumnAndRow($line, $column, '');
             $column++;
         }
         $display_extra_user_fields = true;
@@ -2982,12 +2977,16 @@ class SurveyUtil
         $course_id = api_get_course_int_id();
 
         // First line (questions)
-        $sql = "SELECT questions.question_id, questions.type, questions.survey_question, count(options.question_option_id) as number_of_options
+        $sql = "SELECT
+                    questions.question_id,
+                    questions.type,
+                    questions.survey_question,
+                    count(options.question_option_id) as number_of_options
 				FROM $table_survey_question questions
 				LEFT JOIN $table_survey_question_option options
-				     ON questions.question_id = options.question_id AND options.c_id = $course_id
+                ON questions.question_id = options.question_id AND options.c_id = $course_id
 				WHERE
-				    questions.survey_id = '".Database::escape_string($_GET['survey_id'])."' AND
+				    questions.survey_id = '".intval($_GET['survey_id'])."' AND
 				    questions.c_id = $course_id
 				GROUP BY questions.question_id
 				ORDER BY questions.sort ASC";
@@ -3002,11 +3001,25 @@ class SurveyUtil
                 // We do not show comment and pagebreak question types
                 if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
                     if ($row['number_of_options'] == 0 && $row['type'] == 'open') {
-                        $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES));
+                        $worksheet->SetCellValueByColumnAndRow(
+                            $line,
+                            $column,
+                            api_html_entity_decode(
+                                strip_tags($row['survey_question']),
+                                ENT_QUOTES
+                            )
+                        );
                         $column ++;
                     } else {
                         for ($ii = 0; $ii < $row['number_of_options']; $ii ++) {
-                            $worksheet->write($line, $column, api_html_entity_decode(strip_tags($row['survey_question']), ENT_QUOTES));
+                            $worksheet->SetCellValueByColumnAndRow(
+                                $line,
+                                $column,
+                                api_html_entity_decode(
+                                    strip_tags($row['survey_question']),
+                                    ENT_QUOTES
+                                )
+                            );
                             $column ++;
                         }
                     }
@@ -3020,14 +3033,19 @@ class SurveyUtil
         if ($display_extra_user_fields) {
             // Show the fields names for user fields
             foreach ($extra_user_fields as & $field) {
-                $worksheet->write($line, $column, api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES));
+                $worksheet->SetCellValueByColumnAndRow(
+                    $line,
+                    $column,
+                    api_html_entity_decode(strip_tags($field[3]), ENT_QUOTES)
+                );
                 $column++;
             }
         }
 
         // Getting all the questions and options (second line)
-        $sql = "SELECT 	survey_question.question_id, survey_question.survey_id, survey_question.survey_question, survey_question.display, survey_question.sort, survey_question.type,
-						survey_question_option.question_option_id, survey_question_option.option_text, survey_question_option.sort as option_sort
+        $sql = "SELECT
+                    survey_question.question_id, survey_question.survey_id, survey_question.survey_question, survey_question.display, survey_question.sort, survey_question.type,
+                    survey_question_option.question_option_id, survey_question_option.option_text, survey_question_option.sort as option_sort
 				FROM $table_survey_question survey_question
 				LEFT JOIN $table_survey_question_option survey_question_option
 				ON survey_question.question_id = survey_question_option.question_id AND survey_question_option.c_id = $course_id
@@ -3041,10 +3059,19 @@ class SurveyUtil
             // We show the options if
             // 1. there is no question filter and the export button has not been clicked
             // 2. there is a quesiton filter but the question is selected for display
-            if (!($_POST['submit_question_filter']) || (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))) {
+            if (!($_POST['submit_question_filter']) ||
+                (is_array($_POST['questions_filter']) && in_array($row['question_id'], $_POST['questions_filter']))
+            ) {
                 // We do not show comment and pagebreak question types
                 if ($row['type'] != 'comment' && $row['type'] != 'pagebreak') {
-                    $worksheet->write($line,$column,api_html_entity_decode(strip_tags($row['option_text']), ENT_QUOTES));
+                    $worksheet->SetCellValueByColumnAndRow(
+                        $line,
+                        $column,
+                        api_html_entity_decode(
+                            strip_tags($row['option_text']),
+                            ENT_QUOTES
+                        )
+                    );
                     $possible_answers[$row['question_id']][$row['question_option_id']] = $row['question_option_id'];
                     $possible_answers_type[$row['question_id']] = $row['type'];
                     $column++;
@@ -3060,7 +3087,7 @@ class SurveyUtil
         $sql = "SELECT * FROM $table_survey_answer
                 WHERE c_id = $course_id AND survey_id='".intval($_GET['survey_id'])."' ";
         if ($user_id != 0) {
-            $sql .= "AND user='".Database::escape_string($user_id)."' ";
+            $sql .= "AND user='".intval($user_id)."' ";
         }
         $sql .=	"ORDER BY user ASC";
 
@@ -3068,9 +3095,15 @@ class SurveyUtil
         $result = Database::query($sql);
         while ($row = Database::fetch_array($result)) {
             if ($old_user != $row['user'] && $old_user != '') {
-                $return = SurveyUtil::export_complete_report_row_xls($survey_data, $possible_answers, $answers_of_user, $old_user, true);
+                $return = SurveyUtil::export_complete_report_row_xls(
+                    $survey_data,
+                    $possible_answers,
+                    $answers_of_user,
+                    $old_user,
+                    true
+                );
                 foreach ($return as $elem) {
-                    $worksheet->write($line, $column, $elem);
+                    $worksheet->SetCellValueByColumnAndRow($line, $column, $elem);
                     $column++;
                 }
                 $answers_of_user = array();
@@ -3092,12 +3125,19 @@ class SurveyUtil
             $answers_of_user,
             $old_user,
             true
-        ); // this is to display the last user
+        );
+
+        // this is to display the last user
         foreach ($return as $elem) {
-            $worksheet->write($line, $column, $elem);
+            $worksheet->SetCellValueByColumnAndRow($line, $column, $elem);
             $column++;
         }
-        $workbook->close();
+
+        $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
+        $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
+        $writer->save($file);
+        DocumentManager::file_send_for_download($file, true, $filename);
+
         return null;
     }
 
@@ -3120,7 +3160,9 @@ class SurveyUtil
         $return = array();
         if ($survey_data['anonymous'] == 0) {
             if (intval($user) !== 0) {
-                $sql = 'SELECT firstname, lastname FROM '.Database::get_main_table(TABLE_MAIN_USER).' WHERE user_id='.intval($user);
+                $sql = 'SELECT firstname, lastname
+                        FROM '.Database::get_main_table(TABLE_MAIN_USER).'
+                        WHERE user_id='.intval($user);
                 $rs = Database::query($sql);
                 if($row = Database::fetch_array($rs)) {
                     $user_displayed = api_get_person_name($row['firstname'], $row['lastname']);

+ 19 - 0
main/template/default/layout/footer.tpl

@@ -206,6 +206,25 @@
             });
         });
     };
+
+    /**
+     * Generic function to replace the deprecated jQuery toggle function
+     * @param inId          : id of block to hide / unhide
+     * @param inIdTxt       : id of the button
+     * @param inTxtHide     : text one of the button
+     * @param inTxtUnhide   : text two of the button
+     * @todo : allow to detect if text is from a button or from a <a>
+     */
+    function hideUnhide(inId, inIdTxt, inTxtHide, inTxtUnhide)
+    {
+        if ($('#'+inId).css("display") == "none") {
+            $('#'+inId).show(400);
+            $('#'+inIdTxt).attr("value", inTxtUnhide);
+        } else {
+            $('#'+inId).hide(400);
+            $('#'+inIdTxt).attr("value", inTxtHide);
+        }
+    }
 </script>
 
 {{ execution_stats }}

+ 1 - 0
main/template/default/layout/page_body.tpl

@@ -6,6 +6,7 @@
 {% endif %}
 
 {{ flash_messages }}
+<span id="js_alerts"></span>
 
 {#  Page header #}
 {% if header != '' %}

+ 17 - 57
main/tracking/course_session_report.php

@@ -5,9 +5,9 @@
  * Report
  * @package chamilo.tracking
  */
+
 $cidReset = true;
 require_once '../inc/global.inc.php';
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer.php';
 
 $this_section = "session_my_space";
 
@@ -96,22 +96,22 @@ foreach ($course_list  as $current_course ) {
 	$lp_list = $list->get_flat_list();
 
 	// Looping LPs
-	foreach ($lp_list as $lp_id =>$lp) {
-		$exercise_list = Event::get_all_exercises_from_lp($lp_id, $course_info['real_id']);
-		// Looping Chamilo Exercises in LP
-		foreach ($exercise_list as $exercise) {
-			$exercise_stats = Event::get_all_exercise_event_from_lp(
-				$exercise['path'],
-				$course_info['real_id'],
-				$session_id
-			);
-			// Looping Exercise Attempts
-			foreach ($exercise_stats as $stats) {
-				$attempt_result[$stats['exe_user_id']]['result'] += $stats['exe_result'] / $stats['exe_weighting'];
-				$attempt_result[$stats['exe_user_id']]['attempts']++;
-			}
-		}
-	}
+    foreach ($lp_list as $lp_id =>$lp) {
+        $exercise_list = Event::get_all_exercises_from_lp($lp_id, $course_info['real_id']);
+        // Looping Chamilo Exercises in LP
+        foreach ($exercise_list as $exercise) {
+            $exercise_stats = Event::get_all_exercise_event_from_lp(
+                $exercise['path'],
+                $course_info['real_id'],
+                $session_id
+            );
+            // Looping Exercise Attempts
+            foreach ($exercise_stats as $stats) {
+                $attempt_result[$stats['exe_user_id']]['result'] += $stats['exe_result'] / $stats['exe_weighting'];
+                $attempt_result[$stats['exe_user_id']]['attempts']++;
+            }
+        }
+    }
 	$main_result[$current_course['code']] = $attempt_result;
 }
 
@@ -212,48 +212,8 @@ if (!empty($users) && is_array($users)) {
 	Display::display_warning_message(get_lang('NoResults'));
 }
 
-
 if (!$export_to_xls) {
 	echo $html_result;
 }
 
-$filename = 'exam-reporting-'.date('Y-m-d-h:i:s').'.xls';
-if ($export_to_xls) {
-	echo $html_result;
-	export_complete_report_xls($filename, $export_array);
-	exit;
-}
-
-function sort_user($a, $b) {
-	if (is_numeric($a['score']) && is_numeric($b['score'])) {
-		echo $a['score'].' : '.$b['score'];
-		echo '<br />';
-		if ($a['score'] < $b['score']) {
-			return 1;
-		}
-		return 0;
-	}
-	return 1;
-}
-
-function export_complete_report_xls($filename, $array) {
-	global $charset;
-	$workbook = new Spreadsheet_Excel_Writer();
-	$workbook ->setTempDir(api_get_path(SYS_ARCHIVE_PATH));
-	$workbook->send($filename);
-	$workbook->setVersion(8); // BIFF8
-	$worksheet =& $workbook->addWorksheet('Report');
-	//$worksheet->setInputEncoding(api_get_system_encoding());
-	$worksheet->setInputEncoding($charset);
-	/*
-    $line = 0;
-    $column = 1; // Skip the first column (row titles)
-    foreach ($array as $elem) {
-        $worksheet->write($line, $column, $elem);
-        $column++;
-    }
-    $workbook->close();*/
-	exit;
-}
-
 Display :: display_footer();

+ 32 - 11
main/tracking/exams.php

@@ -1,11 +1,12 @@
 <?php
 /* For licensing terms, see /license.txt */
+
 /**
  * Exams script
  * @package chamilo.tracking
  */
+
 require_once '../inc/global.inc.php';
-//require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer.php';
 
 $toolTable = Database::get_course_table(TABLE_TOOL_LIST);
 $quizTable = Database::get_course_table(TABLE_QUIZ_TEST);
@@ -189,7 +190,7 @@ if (!empty($courseList) && is_array($courseList)) {
         if ($global) {
             $sql = "SELECT count(id) as count
                     FROM $quizTable AS quiz
-                    WHERE active='1' AND c_id = $courseId AND session_id = 0";
+                    WHERE active='1' AND c_id = $courseId AND (session_id = 0 OR session_id IS NULL)";
             $result = Database::query($sql);
             $countExercises = Database::store_result($result);
             $exerciseCount = $countExercises[0]['count'];
@@ -201,7 +202,7 @@ if (!empty($courseList) && is_array($courseList)) {
             $countExercises = Database::store_result($result);
             $exerciseSessionCount = $countExercises[0]['count'];
 
-            $exerciseCount =  $exerciseCount + $exerciseCount *count($newSessionList) + $exerciseSessionCount;
+            $exerciseCount =  $exerciseCount + $exerciseCount * count($newSessionList) + $exerciseSessionCount;
 
             // Add course and session list.
             if ($exerciseCount == 0) {
@@ -238,7 +239,6 @@ if (!empty($courseList) && is_array($courseList)) {
 
                             ORDER BY session_id, quiz.title ASC";
                 } else {
-
                     $sql = "SELECT quiz.title, id, session_id
                             FROM $quizTable AS quiz
                             WHERE
@@ -254,7 +254,8 @@ if (!empty($courseList) && is_array($courseList)) {
             if (Database::num_rows($resultExercises) > 0) {
                 $export_array_global = array();
 
-                while ($exercise = Database::fetch_array($resultExercises)) {
+                while ($exercise = Database::fetch_array($resultExercises, 'ASSOC')) {
+
                     $exerciseSessionId = $exercise['session_id'];
 
                     if (empty($exerciseSessionId)) {
@@ -387,8 +388,10 @@ function sort_user($a, $b) {
         if ($a['score'] < $b['score']) {
             return 1;
         }
+
         return 0;
     }
+
     return 1;
 }
 
@@ -402,8 +405,8 @@ function export_complete_report_xls($filename, $array)
 
     $spreadsheet = new PHPExcel();
     $spreadsheet->setActiveSheetIndex(0);
-
     $worksheet = $spreadsheet->getActiveSheet();
+
     $line = 0;
     $column = 0; //skip the first column (row titles)
 
@@ -478,12 +481,32 @@ function export_complete_report_xls($filename, $array)
     $file = api_get_path(SYS_ARCHIVE_PATH).api_replace_dangerous_char($filename);
     $writer = new PHPExcel_Writer_Excel2007($spreadsheet);
     $writer->save($file);
-    DocumentManager::file_send_for_download($file, false, $filename);
+    DocumentManager::file_send_for_download($file, true, $filename);
     exit;
 }
 
+/**
+ * @param $filter_score
+ * @param $global
+ * @param $exercise
+ * @param $courseInfo
+ * @param $sessionId
+ * @param $newSessionList
+ * @return array
+ */
 function processStudentList($filter_score, $global, $exercise, $courseInfo, $sessionId, $newSessionList)
 {
+    if (
+        (isset($exercise['id']) && empty($exercise['id'])) ||
+        !isset($exercise['id'])
+    ) {
+        return array(
+            'html' => '',
+            'export_array_global' =>  [],
+            'total_students' => 0
+        );
+    }
+
     $exerciseStatsTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
     $courseId = api_get_course_int_id($courseInfo['code']);
 
@@ -547,7 +570,7 @@ function processStudentList($filter_score, $global, $exercise, $courseInfo, $ses
                 WHERE
                     ex.c_id = $courseId AND
                     ex.exe_exo_id = ".$exercise['id']." AND
-                    exe_user_id='".$studentId."' AND
+                    exe_user_id= $studentId AND
                     session_id = $sessionId
                 ";
         $result = Database::query($sql);
@@ -556,7 +579,7 @@ function processStudentList($filter_score, $global, $exercise, $courseInfo, $ses
         $sql = "SELECT exe_id, exe_result, exe_weighting
                 FROM $exerciseStatsTable
                 WHERE
-                    exe_user_id = ".$studentId." AND
+                    exe_user_id = $studentId AND
                     c_id = $courseId AND
                     exe_exo_id = ".$exercise['id']." AND
                     session_id = $sessionId
@@ -669,7 +692,6 @@ function processStudentList($filter_score, $global, $exercise, $courseInfo, $ses
         }
     }
 
-
     if ($global) {
         // Exam taken
         $html .= '<td>';
@@ -710,7 +732,6 @@ function processStudentList($filter_score, $global, $exercise, $courseInfo, $ses
         $html .= '</tr>';
         $export_array_global[] = $globalRow;
     }
-
     return array(
         'html' => $html,
         'export_array_global' => $export_array_global,

+ 39 - 66
main/tracking/lp_results_by_user.php

@@ -1,5 +1,6 @@
 <?php
 /* For licensing terms, see /license.txt */
+
 /**
  *
  * Exercise results from Learning paths
@@ -7,12 +8,8 @@
  * @todo implement pagination
  * @package chamilo.tracking
  */
-/**
- * Code
- */
+
 require_once '../inc/global.inc.php';
-require_once api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php';
-require_once api_get_path(LIBRARY_PATH).'pear/Spreadsheet_Excel_Writer/Writer.php';
 
 $this_section = SECTION_TRACKING;
 
@@ -105,17 +102,16 @@ if (!$export_to_csv) {
 			echo '<br />';
 		}
 	} else {
-	   echo '<a href="courseLog.php?'.api_get_cidreq().'&studentlist=true">'.get_lang('StudentsTracking').'</a>&nbsp;|
+	    echo '<a href="courseLog.php?'.api_get_cidreq().'&studentlist=true">'.get_lang('StudentsTracking').'</a>&nbsp;|
 		     <a href="courseLog.php?'.api_get_cidreq().'&studentlist=false">'.get_lang('CourseTracking').'</a>&nbsp;|&nbsp';
-       echo '<a href="courseLog.php?'.api_get_cidreq().'&studentlist=resources">'.get_lang('ResourcesTracking').'</a>';
+        echo '<a href="courseLog.php?'.api_get_cidreq().'&studentlist=resources">'.get_lang('ResourcesTracking').'</a>';
 		echo ' | '.get_lang('ExamTracking').'';
-         echo '<a href="'.api_get_self().'?export=1&score='.$filter_score.'&exercise_id='.$exercise_id.'"><img align="absbottom" src="../img/excel.gif">&nbsp;'.get_lang('ExportAsXLS').'</a><br /><br />';
+        echo '<a href="'.api_get_self().'?export=1&score='.$filter_score.'&exercise_id='.$exercise_id.'"><img align="absbottom" src="../img/excel.gif">&nbsp;'.get_lang('ExportAsXLS').'</a><br /><br />';
 
 	}
     echo '</div>';
 	echo '<br /><br />';
 	$form->display();
-	//echo '<h3>'.sprintf(get_lang('FilteringWithScoreX'), $filter_score).'%</h3>';
 }
 $main_result = array();
 $session_id = 0;
@@ -125,7 +121,6 @@ foreach($course_list  as $current_course ) {
 	$course_info = api_get_course_info($current_course['code']);
 	$_course = $course_info;
 
-
 	//Getting LP list
 	$list = new LearnpathList('', $current_course['code'], $session_id);
 	$lp_list = $list->get_flat_list();
@@ -142,9 +137,8 @@ foreach($course_list  as $current_course ) {
 				$course_info['real_id'],
 				$session_id
 			);
-			//Looping Exercise Attempts
-			foreach($exercise_stats as $stats) {
-				//$attempt_result[$exercise['id']]['users'][$stats['exe_user_id']][$stats['exe_id']] = array('exe_result' =>$stats['exe_result'],'exe_weighting' =>$stats['exe_weighting']);
+			// Looping Exercise Attempts
+			foreach ($exercise_stats as $stats) {
 				$attempt_result[$exercise['id']]['users'][$stats['exe_user_id']][$stats['exe_id']] = $stats;
 				$user_list[$stats['exe_user_id']] = $stats['exe_user_id'];
 			}
@@ -155,11 +149,14 @@ foreach($course_list  as $current_course ) {
 	}
 	$main_result[$current_course['code']] = $lps;
 }
-//echo '<pre>';print_r($main_result);
+
 if (!empty($user_list)) {
     foreach($user_list as $user_id) {
         $user_data = api_get_user_info($user_id);
-        $user_list_name[$user_id] = api_get_person_name($user_data['firstname'],$user_data['lastname']);
+		$user_list_name[$user_id] = api_get_person_name(
+			$user_data['firstname'],
+			$user_data['lastname']
+		);
     }
 }
 $export_array =  array();
@@ -180,10 +177,10 @@ if (!empty($main_result)) {
             continue;
         }
 
-        foreach($lps as $lp_id => $lp_data) {
+        foreach ($lps as $lp_id => $lp_data) {
             $exercises = $lp_data['exercises'];
 
-            foreach($exercises as $exercise_id => $exercise_data) {
+            foreach ($exercises as $exercise_id => $exercise_data) {
                 $users = $exercise_data['users'];
                 foreach($users as $user_id => $attempts) {
                     $attempt = 1;
@@ -199,7 +196,15 @@ if (!empty($main_result)) {
                         $html_result .= Display::tag('td', $result);
 
                         $html_result .= '</tr>';
-                        $export_array[]= array($course_code, $lp_list_name[$lp_id], $exercise_list_name[$exercise_id], $user_list_name[$user_id], $attempt, api_get_local_time($attempt_data['exe_date']), $result);
+						$export_array[] = array(
+							$course_code,
+							$lp_list_name[$lp_id],
+							$exercise_list_name[$exercise_id],
+							$user_list_name[$user_id],
+							$attempt,
+							api_get_local_time($attempt_data['exe_date']),
+							$result,
+						);
                         $attempt++;
                     }
                 }
@@ -217,55 +222,23 @@ if ($export_to_csv) {
     export_complete_report_csv($filename, $export_array);
 	exit;
 }
-function export_complete_report_csv($filename, $array) {
-        require_once api_get_path(LIBRARY_PATH).'export.lib.inc.php';
-        $header[] = array(get_lang('Course'),get_lang('LearningPath'), get_lang('Exercise'), get_lang('User'),get_lang('Attempt'), get_lang('Date'),get_lang('Results'));
-        if (!empty($array)) {
-            $array = array_merge($header, $array);
-            Export :: arrayToCsv($array, $filename);
-        }
-        exit;
-        /*
-         * Too much encoding problems while exporting to XLS, keep it simple
-         *
-         *
-		global $global, $filter_score;
-		$workbook = new Spreadsheet_Excel_Writer();
-		$workbook ->setTempDir(api_get_path(SYS_ARCHIVE_PATH));
-		$workbook->send($filename);
-		$workbook->setVersion(8); // BIFF8
-		$worksheet =& $workbook->addWorksheet('Report');
-		$worksheet->setInputEncoding(api_get_system_encoding());
-
-		$line = 0;
-		$column = 0; //skip the first column (row titles)
 
-		$worksheet->write($line,$column,get_lang('Course'));
-		$column++;
-		$worksheet->write($line,$column,get_lang('LearningPath'));
-		$column++;
-		$worksheet->write($line,$column,get_lang('Exercise'));
-		$column++;
-		$worksheet->write($line,$column,get_lang('User'));
-		$column++;
-		$worksheet->write($line,$column,get_lang('Attempt'));
-		$column++;
-		$worksheet->write($line,$column,get_lang('Date'));
-		$column++;
-		$worksheet->write($line,$column,get_lang('Results'));
-		$column++;
-		$line++;
-		foreach ($array as $row) {
-			$column = 0;
-			foreach ($row as $item) {
-				$worksheet->write($line,$column,html_entity_decode(strip_tags($item)));
-				$column++;
-			}
-			$line++;
-		}
-		$line++;
+function export_complete_report_csv($filename, $array)
+{
+	$header[] = array(
+		get_lang('Course'),
+		get_lang('LearningPath'),
+		get_lang('Exercise'),
+		get_lang('User'),
+		get_lang('Attempt'),
+		get_lang('Date'),
+		get_lang('Results'),
+	);
+	if (!empty($array)) {
+		$array = array_merge($header, $array);
+		Export :: arrayToCsv($array, $filename);
+	}
+	exit;
 
-		$workbook->close();
-		exit;*/
 }
 Display :: display_footer();

+ 0 - 41
main/tracking/question_course_report.php

@@ -215,45 +215,4 @@ if (!$export_to_xls) {
 	echo $html_result;
 }
 
-$filename = 'exam-reporting-'.date('Y-m-d-h:i:s').'.xls';
-if ($export_to_xls) {
-	echo $html_result;
-	export_complete_report_xls($filename, $export_array);
-	exit;
-}
-
-function sort_user($a, $b)
-{
-	if (is_numeric($a['score']) && is_numeric($b['score'])) {
-		echo $a['score'].' : '.$b['score'];
-		echo '<br />';
-		if ($a['score'] < $b['score']) {
-			return 1;
-		}
-		return 0;
-	}
-	return 1;
-}
-
-function export_complete_report_xls($filename, $array)
-{
-	global $charset;
-	$workbook = new Spreadsheet_Excel_Writer();
-	$workbook ->setTempDir(api_get_path(SYS_ARCHIVE_PATH));
-	$workbook->send($filename);
-	$workbook->setVersion(8); // BIFF8
-	$worksheet =& $workbook->addWorksheet('Report');
-	//$worksheet->setInputEncoding(api_get_system_encoding());
-	$worksheet->setInputEncoding($charset);
-	/*
-    $line = 0;
-    $column = 1; // Skip the first column (row titles)
-    foreach ($array as $elem) {
-        $worksheet->write($line, $column, $elem);
-        $column++;
-    }
-    $workbook->close();*/
-	exit;
-}
-
 Display :: display_footer();

+ 1 - 1
main/user/subscribe_user.php

@@ -778,7 +778,7 @@ function reg_filter($user_id) {
  */
 
 function active_filter($active, $url_params, $row) {
-	global $_user;
+	$_user = api_get_user_info();
 	if ($active=='1') {
 		$action='AccountActive';
 		$image='accept';

+ 9 - 5
src/Chamilo/CoreBundle/Entity/Repository/SequenceRepository.php

@@ -6,6 +6,7 @@ namespace Chamilo\CoreBundle\Entity\Repository;
 use Chamilo\CoreBundle\Entity\SequenceResource;
 use Doctrine\ORM\EntityRepository;
 use Fhaculty\Graph\Vertex;
+use Fhaculty\Graph\Set\Vertices;
 
 /**
  * Class SequenceRepository
@@ -40,8 +41,8 @@ class SequenceRepository extends EntityRepository
      * @return array
      */
     public function getRequirementAndDependencies($resourceId, $type)
-    {        $sequence = $this->findRequirementForResource($resourceId, $type);
-
+    {
+        $sequence = $this->findRequirementForResource($resourceId, $type);
         $result = ['requirements' => '', 'dependencies' => ''];
         if ($sequence && $sequence->hasGraph()) {
             $graph = $sequence->getSequence()->getUnSerializeGraph();
@@ -109,6 +110,7 @@ class SequenceRepository extends EntityRepository
      * Get the requirements for a resource only
      * @param int $resourceId The resource ID
      * @param int $type The type of sequence resource
+     *
      * @return array
      */
     public function getRequirements($resourceId, $type)
@@ -164,6 +166,7 @@ class SequenceRepository extends EntityRepository
      * Get the requirements and dependencies within a sequence for a resource
      * @param int $resourceId The resource ID
      * @param int $type The type of sequence resource
+     *
      * @return array
      */
     public function getRequirementsAndDependenciesWithinSequences($resourceId, $type)
@@ -209,11 +212,12 @@ class SequenceRepository extends EntityRepository
     }
 
     /**
-     * Get sessiones from vertices
-     * @param \Fhaculty\Graph\Set\Vertices $verticesEdges The vertices
+     * Get sessions from vertices
+     * @param Vertices $verticesEdges The vertices
+     *
      * @return array
      */
-    private function findSessionFromVerticesEdges(\Fhaculty\Graph\Set\Vertices $verticesEdges)
+    private function findSessionFromVerticesEdges(Vertices $verticesEdges)
     {
         $sessionVertices = [];
 

+ 6 - 9
src/Chamilo/CoreBundle/Entity/Repository/SessionRepository.php

@@ -1,5 +1,6 @@
 <?php
 /* For licensing terms, see /license.txt */
+
 namespace Chamilo\CoreBundle\Entity\Repository;
 
 use Doctrine\ORM\EntityRepository;
@@ -11,7 +12,8 @@ use Chamilo\CoreBundle\Entity\Course;
  * SessionRepository
  *
  * @package Chamilo\CoreBundle\Entity\Repository
- * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @author  Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @author  Julio Montoya <gugli100@gmail.com>
  */
 class SessionRepository extends EntityRepository
 {
@@ -19,20 +21,15 @@ class SessionRepository extends EntityRepository
     /**
      * Get session's courses ordered by position in session_rel_course
      * @param Session $session The session
+     *
      * @return \Doctrine\ORM\QueryBuilder
      */
     public function getCoursesOrderedByPosition(Session $session)
     {
         $queryBuilder = $this->createQueryBuilder('s');
 
-        $queryBuilder->select('c')
-            ->innerJoin('s.courses', 'session_courses')
-            ->innerJoin(
-                'ChamiloCoreBundle:SessionRelCourse',
-                'src',
-                Join::WITH,
-                'session_courses.course = src.course'
-            )
+        $queryBuilder->select('DISTINCT c ')
+            ->innerJoin('s.courses', 'src')
             ->innerJoin(
                 'ChamiloCoreBundle:Course',
                 'c',

+ 100 - 42
user_portal.php

@@ -35,11 +35,110 @@ $userId = api_get_user_id();
 
 /* Constants and CONFIGURATION parameters */
 $load_dirs = api_get_setting('show_documents_preview');
+$displayMyCourseViewBySessionLink = api_get_configuration_value('my_courses_view_by_session');
+
+
+$nameTools = get_lang('MyCourses');
+
+/*
+    Header
+    Include the HTTP, HTML headers plus the top banner.
+*/
+if ($load_dirs) {
+    $url = api_get_path(WEB_AJAX_PATH).'document.ajax.php?a=document_preview';
+    $folder_icon = api_get_path(WEB_IMG_PATH).'icons/22/folder.png';
+    $close_icon = api_get_path(WEB_IMG_PATH).'loading1.gif';
+
+    $htmlHeadXtra[] =  '<script>
+	$(document).ready(function() {
+		$(".document_preview_container").hide();
+		$(".document_preview").click(function() {
+			var my_id = this.id;
+			var course_id  = my_id.split("_")[2];
+			var session_id = my_id.split("_")[3];
+
+			//showing div
+			$(".document_preview_container").hide();
+
+			$("#document_result_" +course_id+"_" + session_id).show();
+
+			//Loading
+			var image = $("img", this);
+			image.attr("src", "'.$close_icon.'");
+
+			$.ajax({
+				url: "'.$url.'",
+				data: "course_id="+course_id+"&session_id="+session_id,
+	            success: function(return_value) {
+	            	image.attr("src", "'.$folder_icon.'");
+	            	$("#document_result_" +course_id+"_" + session_id).html(return_value);
+	            }
+	        });
+
+		});
+	});
+	</script>';
+}
+if ($displayMyCourseViewBySessionLink) {
+    $htmlHeadXtra[] = '
+    <script type="text/javascript">
+        userId = ' . $userId . '
+        $(document).ready(function() {
+            changeMyCoursesView($.cookie("defaultMyCourseView"+userId));
+        });
+
+        /**
+        * Keep in cookie the last teacher view for the My Courses Tab. default view, or view by session
+        * @param inView
+        */
+        function changeMyCoursesView(inView)
+        {
+            $.cookie("defaultMyCourseView"+userId, inView, { expires: 365 });
+            if (inView == ' . IndexManager::VIEW_BY_SESSION . ') {
+                $("#viewBySession").addClass("btn-primary");
+                $("#viewByDefault").removeClass("btn-primary");
+            } else {
+                $("#viewByDefault").addClass("btn-primary");
+                $("#viewBySession").removeClass("btn-primary");
+            }
+        }
+	</script>
+';
+}
 
 $controller = new IndexManager(get_lang('MyCourses'));
 
 // Main courses and session list
-$courseAndSessions = $controller->returnCoursesAndSessions($userId);
+//$courseAndSessions = $controller->returnCoursesAndSessions($userId);
+
+// Main courses and session list
+if (isset($_COOKIE['defaultMyCourseView'.$userId]) &&
+    $_COOKIE['defaultMyCourseView'.$userId] == IndexManager::VIEW_BY_SESSION && $displayMyCourseViewBySessionLink
+) {
+    $courseAndSessions = $controller->returnCoursesAndSessionsViewBySession($userId);
+    IndexManager::setDefaultMyCourseView(IndexManager::VIEW_BY_SESSION, $userId);
+} else {
+    $courseAndSessions = $controller->returnCoursesAndSessions($userId);
+    IndexManager::setDefaultMyCourseView(IndexManager::VIEW_BY_DEFAULT, $userId);
+}
+
+// if teacher, session coach or admin, display the button to change te course view
+
+if ($displayMyCourseViewBySessionLink &&
+    (api_is_drh() || api_is_course_coach() || api_is_platform_admin() || api_is_session_admin() || api_is_teacher())
+) {
+    $courseAndSessions['html'] = "<div class='view-by-session-link'>
+		<div class='btn-group pull-right'>
+		<a class='btn btn-default' id='viewByDefault' href='user_portal.php' onclick='changeMyCoursesView(\"".IndexManager::VIEW_BY_DEFAULT."\")'>
+		".get_lang('MyCoursesDefaultView')."
+		</a>
+		<a class='btn btn-default' id='viewBySession' href='user_portal.php' onclick='changeMyCoursesView(\"".IndexManager::VIEW_BY_SESSION."\")'>
+		".get_lang('MyCoursesSessionView')."
+		</a>
+		</div>
+	</div><br /><br />
+	".$courseAndSessions['html'];
+}
 
 // Check if a user is enrolled only in one course for going directly to the course after the login.
 if (api_get_setting('go_to_course_after_login') == 'true') {
@@ -87,47 +186,6 @@ if (api_get_setting('go_to_course_after_login') == 'true') {
     }
 }
 
-$nameTools = get_lang('MyCourses');
-
-/*
-    Header
-    Include the HTTP, HTML headers plus the top banner.
-*/
-if ($load_dirs) {
-	$url = api_get_path(WEB_AJAX_PATH).'document.ajax.php?a=document_preview';
-	$folder_icon = api_get_path(WEB_IMG_PATH).'icons/22/folder.png';
-	$close_icon = api_get_path(WEB_IMG_PATH).'loading1.gif';
-
-	$htmlHeadXtra[] =  '<script>
-	$(document).ready(function() {
-		$(".document_preview_container").hide();
-		$(".document_preview").click(function() {
-			var my_id = this.id;
-			var course_id  = my_id.split("_")[2];
-			var session_id = my_id.split("_")[3];
-
-			//showing div
-			$(".document_preview_container").hide();
-
-			$("#document_result_" +course_id+"_" + session_id).show();
-
-			//Loading
-			var image = $("img", this);
-			image.attr("src", "'.$close_icon.'");
-
-			$.ajax({
-				url: "'.$url.'",
-				data: "course_id="+course_id+"&session_id="+session_id,
-	            success: function(return_value) {
-	            	image.attr("src", "'.$folder_icon.'");
-	            	$("#document_result_" +course_id+"_" + session_id).html(return_value);
-	            }
-	        });
-
-		});
-	});
-	</script>';
-}
 
 //Show the chamilo mascot
 if (empty($courseAndSessions['html']) && !isset($_GET['history'])) {