Julio Montoya преди 11 години
родител
ревизия
9ceeb3b2d8
променени са 92 файла, в които са добавени 6350 реда и са изтрити 694 реда
  1. 10 6
      plugin/add_cas_login_button/index.php
  2. 1 3
      plugin/add_cas_login_button/plugin.php
  3. 6 3
      plugin/add_cas_logout_button/index.php
  4. 2 4
      plugin/add_cas_logout_button/plugin.php
  5. 16 11
      plugin/add_facebook_login_button/plugin.php
  6. 32 14
      plugin/add_shibboleth_login_button/plugin.php
  7. 4 2
      plugin/bbb/config.php
  8. 13 12
      plugin/bbb/lib/bbb.lib.php
  9. 2 2
      plugin/bbb/lib/bbb_plugin.class.php
  10. 2 2
      plugin/bbb/listing.php
  11. 1 3
      plugin/bbb/start.php
  12. 78 0
      plugin/before_login/index.php
  13. 51 0
      plugin/before_login/plugin.php
  14. 10 0
      plugin/before_login/readme.txt
  15. 14 0
      plugin/before_login/template.tpl
  16. 165 154
      plugin/dashboard/block_course/block_course.class.php
  17. 189 164
      plugin/dashboard/block_daily/block_daily.class.php
  18. 58 58
      plugin/dashboard/block_evaluation_graph/block_evaluation_graph.class.php
  19. 8 9
      plugin/dashboard/block_global_info/block_global_info.class.php
  20. 24 15
      plugin/dashboard/block_session/block_session.class.php
  21. 17 15
      plugin/dashboard/block_student/block_student.class.php
  22. 24 12
      plugin/dashboard/block_student_graph/block_student_graph.class.php
  23. 69 54
      plugin/dashboard/block_teacher/block_teacher.class.php
  24. 44 33
      plugin/dashboard/block_teacher_graph/block_teacher_graph.class.php
  25. 2 2
      plugin/date/plugin.php
  26. 7 4
      plugin/ext_auth_chamilo_logout_button_behaviour/index.php
  27. 2 3
      plugin/ext_auth_chamilo_logout_button_behaviour/plugin.php
  28. 0 2
      plugin/formLogin_hide_unhide/plugin.php
  29. 2 2
      plugin/hello_world/index.php
  30. 7 7
      plugin/hello_world/plugin.php
  31. 1 1
      plugin/olpc_peru_filter/config.php
  32. 12 0
      plugin/openmeetings/config.php
  33. 10 0
      plugin/openmeetings/course_index.php
  34. 1 0
      plugin/openmeetings/index.php
  35. 12 0
      plugin/openmeetings/install.php
  36. 57 0
      plugin/openmeetings/lang/english.php
  37. 50 0
      plugin/openmeetings/lang/french.php
  38. 53 0
      plugin/openmeetings/lang/spanish.php
  39. 631 0
      plugin/openmeetings/lib/openmeetings.class.php
  40. 24 0
      plugin/openmeetings/lib/openmeetings_api.php
  41. 474 0
      plugin/openmeetings/lib/openmeetings_gateway.php
  42. 91 0
      plugin/openmeetings/lib/openmeetings_plugin.class.php
  43. 181 0
      plugin/openmeetings/lib/openmeetings_rest_service.php
  44. 115 0
      plugin/openmeetings/lib/room.class.php
  45. 16 0
      plugin/openmeetings/lib/session.class.php
  46. 31 0
      plugin/openmeetings/lib/user.class.php
  47. 112 0
      plugin/openmeetings/listing.php
  48. 66 0
      plugin/openmeetings/listing.tpl
  49. 4 0
      plugin/openmeetings/plugin.php
  50. 16 0
      plugin/openmeetings/readme.txt
  51. 70 0
      plugin/openmeetings/start.php
  52. 13 0
      plugin/openmeetings/uninstall.php
  53. 1 0
      plugin/rss/plugin.php
  54. 33 28
      plugin/search_course/lib/register_course_widget.class.php
  55. 30 30
      plugin/search_course/lib/search_course_widget.class.php
  56. 2 1
      plugin/search_course/plugin.php
  57. 7 7
      plugin/share_buttons/plugin.php
  58. 2 2
      plugin/show_regions/index.php
  59. 11 12
      plugin/show_user_info/index.php
  60. 10 12
      plugin/show_user_info/plugin.php
  61. 0 2
      plugin/static/index.php
  62. 2 3
      plugin/static/lib/static_plugin.class.php
  63. 1 0
      plugin/static/plugin.php
  64. 10 0
      plugin/ticket/config.install.php
  65. 45 0
      plugin/ticket/config.php
  66. 137 0
      plugin/ticket/database.php
  67. 1 0
      plugin/ticket/index.php
  68. 13 0
      plugin/ticket/install.php
  69. 35 0
      plugin/ticket/lang/english.php
  70. 33 0
      plugin/ticket/lang/french.php
  71. 68 0
      plugin/ticket/lang/spanish.php
  72. 66 0
      plugin/ticket/lib/ticket.class.php
  73. 98 0
      plugin/ticket/lib/ticket_plugin.class.php
  74. 4 0
      plugin/ticket/plugin.php
  75. 1 0
      plugin/ticket/readme.txt
  76. 46 0
      plugin/ticket/s/assign_tickets.php
  77. 27 0
      plugin/ticket/s/course_user_list.php
  78. 42 0
      plugin/ticket/s/download.php
  79. 4 0
      plugin/ticket/s/index.php
  80. 293 0
      plugin/ticket/s/myticket.php
  81. 447 0
      plugin/ticket/s/new_ticket.php
  82. 289 0
      plugin/ticket/s/report.php
  83. 246 0
      plugin/ticket/s/send_ticket.php
  84. 15 0
      plugin/ticket/s/test.html
  85. 673 0
      plugin/ticket/s/ticket.class.php
  86. 26 0
      plugin/ticket/s/ticket_assign_log.php
  87. 357 0
      plugin/ticket/s/ticket_details.php
  88. 101 0
      plugin/ticket/s/tutor.php
  89. 190 0
      plugin/ticket/s/tutor_report.lib.php
  90. 16 0
      plugin/ticket/s/update_report.php
  91. 55 0
      plugin/ticket/start.php
  92. 13 0
      plugin/ticket/uninstall.php

+ 10 - 6
plugin/add_cas_login_button/index.php

@@ -1,23 +1,27 @@
 <?php
 // Show the CAS button to login using CAS
-require_once(api_get_path(SYS_PATH).'main/auth/cas/authcas.php');
+require_once api_get_path(SYS_PATH).'main/auth/cas/authcas.php';
 
-$_template['show_message']   = false;
+$_template['show_message'] = false;
 
 if (api_is_anonymous()) {
     $_template['cas_activated'] = api_is_cas_activated();
     $_template['cas_configured'] = cas_configured();
-    $_template['show_message']   = true;
+    $_template['show_message'] = true;
     // the default title
     $button_label = "Connexion via CAS";
     if (!empty($plugin_info['settings']['add_cas_login_button_cas_button_label'])) {
-        $button_label = api_htmlentities($plugin_info['settings']['add_cas_login_button_cas_button_label']);
+        $button_label = api_htmlentities(
+            $plugin_info['settings']['add_cas_login_button_cas_button_label']
+        );
     }
     // the comm
-    $comm_label = api_htmlentities($plugin_info['settings']['add_cas_login_button_cas_button_comment']);;
+    $comm_label = api_htmlentities(
+        $plugin_info['settings']['add_cas_login_button_cas_button_comment']
+    );;
     // URL of the image
     $url_label = $plugin_info['settings']['add_cas_login_button_cas_image_url'];
-    
+
     $_template['button_label'] = $button_label;
     $_template['comm_label'] = $comm_label;
     $_template['url_label'] = $url_label;

+ 1 - 3
plugin/add_cas_login_button/plugin.php

@@ -9,8 +9,6 @@
  * Plugin details (must be present)
  */
 
-
-
 //the plugin title
 $plugin_info['title']      = 'Add a button to login using CAS';
 
@@ -26,7 +24,7 @@ $form = new FormValidator('add_cas_button_form');
 $form->addElement('text', 'cas_button_label', 'CAS connexion title', '');
 $form->addElement('text', 'cas_button_comment', 'CAS connexion description', '');
 $form->addElement('text', 'cas_image_url', 'Logo URL if any (image, 50px height)');
-$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));  
+$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));
 //get default value for form
 $tab_default_add_cas_login_button_cas_button_label = api_get_setting('add_cas_login_button_cas_button_label');
 $tab_default_add_cas_login_button_cas_button_comment = api_get_setting('add_cas_login_button_cas_button_comment');

+ 6 - 3
plugin/add_cas_logout_button/index.php

@@ -3,7 +3,10 @@
 global $_user;
 $_template['show_message']   = false;
 
-if (!api_is_anonymous() && api_get_setting('cas_activate') == 'true' && $_user['auth_source'] == CAS_AUTH_SOURCE) {
+if (!api_is_anonymous() &&
+    api_get_setting('cas_activate') == 'true' &&
+    $_user['auth_source'] == CAS_AUTH_SOURCE
+) {
     $_template['show_message']   = true;
     // the default title
     $logout_label = "Deconnexion de CAS";
@@ -14,8 +17,8 @@ if (!api_is_anonymous() && api_get_setting('cas_activate') == 'true' && $_user['
     $logout_comment = api_htmlentities($plugin_info['settings']['add_cas_logout_button_cas_logout_comment']);;
     // URL of the image
     $logout_image_url = $plugin_info['settings']['add_cas_logout_button_cas_logout_image_url'];
-    
+
     $_template['logout_label'] = $logout_label;
     $_template['logout_comment'] = $logout_comment;
     $_template['logout_image_url'] = $logout_image_url;
-}
+}

+ 2 - 4
plugin/add_cas_logout_button/plugin.php

@@ -9,8 +9,6 @@
  * Plugin details (must be present)
  */
 
-
-
 //the plugin title
 $plugin_info['title']      = 'Add a button to logout from CAS';
 
@@ -25,7 +23,7 @@ $form = new FormValidator('add_cas_button_form');
 $form->addElement('text', 'cas_logout_label', 'CAS logout title', '');
 $form->addElement('text', 'cas_logout_comment', 'CAS logout description', '');
 $form->addElement('text', 'cas_logout_image_url', 'Logo URL if any (image, 50px height)');
-$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));  
+$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));
 //get default value for form
 $tab_default_add_cas_logout_button_cas_logout_label = api_get_setting('add_cas_logout_button_cas_logout_label');
 $tab_default_add_cas_logout_button_cas_logout_comment = api_get_setting('add_cas_logout_button_cas_logout_comment');
@@ -37,5 +35,5 @@ $form->setDefaults($defaults);
 //display form
 $plugin_info['settings_form'] = $form;
 
-//set the smarty templates that are going to be used
+// Set the templates that are going to be used
 $plugin_info['templates']   = array('template.tpl');

+ 16 - 11
plugin/add_facebook_login_button/plugin.php

@@ -9,27 +9,32 @@
  * Plugin details (must be present)
  */
 
-
-
 //the plugin title
-$plugin_info['title']      = 'Add a button to login using FACEBOOK account';
+$plugin_info['title'] = 'Add a button to login using FACEBOOK account';
 
 //the comments that go with the plugin
-$plugin_info['comment']     = "If Facebook authntification is activated, this plugin add a button Facebook Connexion on the login page. Configure plugin to add title, comment and logo. Should be place in login_top region";
+$plugin_info['comment'] = "If Facebook authntification is activated, this plugin add a button Facebook Connexion on the login page. Configure plugin to add title, comment and logo. Should be place in login_top region";
 //the plugin version
-$plugin_info['version']     = '1.0';
+$plugin_info['version'] = '1.0';
 //the plugin author
-$plugin_info['author']      = 'Hubert Borderiou';
+$plugin_info['author'] = 'Hubert Borderiou';
 //the plugin configuration
 $form = new FormValidator('add_facebook_button_form');
-$form->addElement('text', 'facebook_button_url', 'Facebook connexion image URL', '');
-$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));  
+$form->addElement(
+    'text',
+    'facebook_button_url',
+    'Facebook connexion image URL',
+    ''
+);
+$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));
 //get default value for form
-$tab_default_add_facebook_login_button_facebook_button_url = api_get_setting('add_facebook_login_button_facebook_button_url');
+$tab_default_add_facebook_login_button_facebook_button_url = api_get_setting(
+    'add_facebook_login_button_facebook_button_url'
+);
 $defaults['facebook_button_url'] = $tab_default_add_facebook_login_button_facebook_button_url['add_facebook_login_button'];
 $form->setDefaults($defaults);
 //display form
 $plugin_info['settings_form'] = $form;
 
-//set the smarty templates that are going to be used
-$plugin_info['templates']   = array('template.tpl');
+// Set the templates that are going to be used
+$plugin_info['templates'] = array('template.tpl');

+ 32 - 14
plugin/add_shibboleth_login_button/plugin.php

@@ -9,28 +9,46 @@
  * Plugin details (must be present)
  */
 
-
-
 //the plugin title
-$plugin_info['title']      = 'Add a button to login using Shibboleth';
+$plugin_info['title'] = 'Add a button to login using Shibboleth';
 
 //the comments that go with the plugin
-$plugin_info['comment']     = "If Shibboleth is configured, this plugin add a text and a button on the login page to login with Shibboleth. Configure plugin to add title, comment and logo.";
+$plugin_info['comment'] = "If Shibboleth is configured, this plugin add a text and a button on the login page to login with Shibboleth. Configure plugin to add title, comment and logo.";
 //the plugin version
-$plugin_info['version']     = '1.0';
+$plugin_info['version'] = '1.0';
 //the plugin author
-$plugin_info['author']      = 'Hubert Borderiou';
+$plugin_info['author'] = 'Hubert Borderiou';
 
 //the plugin configuration
 $form = new FormValidator('add_shibboleth_button_form');
-$form->addElement('text', 'shibboleth_button_label', 'shibboleth connexion title', '');
-$form->addElement('text', 'shibboleth_button_comment', 'shibboleth connexion description', '');
-$form->addElement('text', 'shibboleth_image_url', 'Logo URL if any (image, 50px height)');
-$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));  
+$form->addElement(
+    'text',
+    'shibboleth_button_label',
+    'shibboleth connexion title',
+    ''
+);
+$form->addElement(
+    'text',
+    'shibboleth_button_comment',
+    'shibboleth connexion description',
+    ''
+);
+$form->addElement(
+    'text',
+    'shibboleth_image_url',
+    'Logo URL if any (image, 50px height)'
+);
+$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));
 //get default value for form
-$tab_default_add_shibboleth_login_button_shibboleth_button_label = api_get_setting('add_shibboleth_login_button_shibboleth_button_label');
-$tab_default_add_shibboleth_login_button_shibboleth_button_comment = api_get_setting('add_shibboleth_login_button_shibboleth_button_comment');
-$tab_default_add_shibboleth_login_button_shibboleth_image_url = api_get_setting('add_shibboleth_login_button_shibboleth_image_url');
+$tab_default_add_shibboleth_login_button_shibboleth_button_label = api_get_setting(
+    'add_shibboleth_login_button_shibboleth_button_label'
+);
+$tab_default_add_shibboleth_login_button_shibboleth_button_comment = api_get_setting(
+    'add_shibboleth_login_button_shibboleth_button_comment'
+);
+$tab_default_add_shibboleth_login_button_shibboleth_image_url = api_get_setting(
+    'add_shibboleth_login_button_shibboleth_image_url'
+);
 $defaults = array();
 $defaults['shibboleth_button_label'] = $tab_default_add_shibboleth_login_button_shibboleth_button_label['add_shibboleth_login_button'];
 $defaults['shibboleth_button_comment'] = $tab_default_add_shibboleth_login_button_shibboleth_button_comment['add_shibboleth_login_button'];
@@ -40,4 +58,4 @@ $form->setDefaults($defaults);
 $plugin_info['settings_form'] = $form;
 
 //set the templates that are going to be used
-$plugin_info['templates']   = array('template.tpl');
+$plugin_info['templates'] = array('template.tpl');

+ 4 - 2
plugin/bbb/config.php

@@ -3,7 +3,9 @@
 
 /* bbb parameters that will be registered in the course settings */
 
-require_once __DIR__.'/../../main/inc/global.inc.php';
+require_once '../../main/inc/global.inc.php';
+require_once api_get_path(LIBRARY_PATH).'plugin.class.php';
+
 require_once 'lib/bbb.lib.php';
 require_once 'lib/bbb_api.php';
-require_once 'lib/bbb_plugin.class.php';
+require_once 'lib/bbb_plugin.class.php';

+ 13 - 12
plugin/bbb/lib/bbb.lib.php

@@ -1,6 +1,6 @@
 <?php
 /**
- * This script initiates a videoconference session, calling the BigBlueButton
+ * This script initiates a videoconference session, calling the BigBlueButton 
  * API
  * @package chamilo.plugin.bigbluebutton
  */
@@ -147,7 +147,7 @@ class bbb {
         }
     }
     /**
-     * Tells whether the given meeting exists and is running
+     * Tells whether the given meeting exists and is running 
      * (using course code as name)
      * @param string Meeting name (usually the course code)
      * @return bool True if meeting exists, false otherwise
@@ -246,14 +246,14 @@ class bbb {
         foreach ($meeting_list as $meeting_db) {
             $meeting_bbb = $this->get_meeting_info(array('meetingId' => $meeting_db['id'], 'password' => $pass));
 
-            $meeting_bbb['end_url'] = api_get_self().'?action=end&id='.$meeting_db['id'];
+            $meeting_bbb['end_url'] = api_get_self().'?'.api_get_cidreq().'&action=end&id='.$meeting_db['id'];
 
             if ((string)$meeting_bbb['returncode'] == 'FAILED') {
                 if ($meeting_db['status'] == 1 && $this->is_teacher()) {
                     $this->end_meeting($meeting_db['id']);
                 }
             } else {
-                $meeting_bbb['add_to_calendar_url'] = api_get_self().'?action=add_to_calendar&id='.$meeting_db['id'].'&start='.api_strtotime($meeting_db['created_at']);
+                $meeting_bbb['add_to_calendar_url'] = api_get_self().'?'.api_get_cidreq().'&action=add_to_calendar&id='.$meeting_db['id'].'&start='.api_strtotime($meeting_db['created_at']);
             }
 
             $record_array = array();
@@ -278,9 +278,9 @@ class bbb {
                             if (is_array($record) && isset($record['recordId'])) {
                                 $url = Display::url(get_lang('ViewRecord'), $record['playbackFormatUrl'], array('target' => '_blank'));
                                 if ($this->is_teacher()) {
-                                    $url .= Display::url(Display::return_icon('link.gif',get_lang('CopyToLinkTool')), api_get_self().'?action=copy_record_to_link_tool&id='.$meeting_db['id'].'&record_id='.$record['recordId']);
-                                    $url .= Display::url(Display::return_icon('agenda.png',get_lang('AddToCalendar')), api_get_self().'?action=add_to_calendar&id='.$meeting_db['id'].'&start='.api_strtotime($meeting_db['created_at']).'&url='.$record['playbackFormatUrl']);
-                                    $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?action=delete_record&id='.$record['recordId']);
+                                    $url .= Display::url(Display::return_icon('link.gif',get_lang('CopyToLinkTool')), api_get_self().'?'.api_get_cidreq().'&action=copy_record_to_link_tool&id='.$meeting_db['id'].'&record_id='.$record['recordId']);
+                                    $url .= Display::url(Display::return_icon('agenda.png',get_lang('AddToCalendar')), api_get_self().'?'.api_get_cidreq().'&action=add_to_calendar&id='.$meeting_db['id'].'&start='.api_strtotime($meeting_db['created_at']).'&url='.$record['playbackFormatUrl']);
+                                    $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?'.api_get_cidreq().'&action=delete_record&id='.$record['recordId']);
                                 }
                                 //$url .= api_get_self().'?action=publish&id='.$record['recordID'];
                                 $count++;
@@ -309,14 +309,15 @@ class bbb {
                         }
                     }
                 }
+                //var_dump($record_array);
                 $item['show_links']  = implode('<br />', $record_array);
             }
 
             $item['created_at'] = api_convert_and_format_date($meeting_db['created_at']);
             //created_at
 
-            $item['publish_url'] = api_get_self().'?action=publish&id='.$meeting_db['id'];
-            $item['unpublish_url'] = api_get_self().'?action=unpublish&id='.$meeting_db['id'];
+            $item['publish_url'] = api_get_self().'?'.api_get_cidreq().'&action=publish&id='.$meeting_db['id'];
+            $item['unpublish_url'] = api_get_self().'?'.api_get_cidreq().'&action=unpublish&id='.$meeting_db['id'];
 
             if ($meeting_db['status'] == 1) {
                 $joinParams = array(
@@ -413,8 +414,8 @@ class bbb {
         if (empty($ids) or (is_array($ids) && count($ids)==0)) { return false; }
         $recordingParams = array(
            /*
-            * NOTE: Set the recordId below to a valid id after you have
-            * created a recorded meeting, and received a real recordID
+            * NOTE: Set the recordId below to a valid id after you have 
+            * created a recorded meeting, and received a real recordID 
             * back from your BBB server using the
             * getRecordingsWithXmlResponseArray method.
             */
@@ -437,10 +438,10 @@ class bbb {
         if (empty($id) or empty($record_id)) {
             return false;
         }
+        require_once api_get_path(LIBRARY_PATH).'link.lib.php';
         $records =  BigBlueButtonBN::getRecordingsArray($id, $this->url, $this->salt);
         if (!empty($records)) {
             foreach ($records as $record) {
-                //error_log($record['recordID']);
                 if ($record['recordID'] == $record_id) {
                     if (is_array($record) && isset($record['recordID']) && isset($record['playbacks'])) {
                         foreach ($record['playbacks'] as $item) {

+ 2 - 2
plugin/bbb/lib/bbb_plugin.class.php

@@ -70,7 +70,7 @@ class BBBPlugin extends Plugin
         Database::query($sql);
 
         //hack to get rid of Database::query warning (please add c_id...)
-        $sql = "DELETE FROM $t_tool WHERE name = 'videoconference' AND c_id = c_id";
+        $sql = "DELETE FROM $t_tool WHERE name = 'bbb' AND c_id = c_id";
         Database::query($sql);
 
         $sql = "DROP TABLE IF EXISTS plugin_bbb_meeting";
@@ -79,4 +79,4 @@ class BBBPlugin extends Plugin
         //Deleting course settings
         $this->uninstall_course_fields_in_all_courses();
     }
-}
+}

+ 2 - 2
plugin/bbb/listing.php

@@ -11,8 +11,7 @@ $course_plugin = 'bbb'; //needed in order to load the plugin lang variables
 require_once dirname(__FILE__).'/config.php';
 $plugin = BBBPlugin::create();
 $tool_name = $plugin->get_lang('Videoconference');
-
-$tpl = $app['template'];
+$tpl = new Template($tool_name);
 
 $bbb = new bbb();
 $action = isset($_GET['action']) ? $_GET['action'] : null;
@@ -91,6 +90,7 @@ $tpl->assign('users_online', $users_online);
 $tpl->assign('bbb_status', $status);
 $tpl->assign('show_join_button', $show_join_button);
 
+//$tpl->assign('actions', $actions);
 $tpl->assign('message', $message);
 $listing_tpl = 'bbb/listing.tpl';
 $content = $tpl->fetch($listing_tpl);

+ 1 - 3
plugin/bbb/start.php

@@ -10,9 +10,7 @@
 $course_plugin = 'bbb'; //needed in order to load the plugin lang variables
 require_once dirname(__FILE__).'/config.php';
 $tool_name = get_lang('Videoconference');
-$app['title'] = $tool_name;
-$tpl = $app['template'];
-
+$tpl = new Template($tool_name);
 $bbb = new bbb();
 
 if ($bbb->plugin_enabled) {

+ 78 - 0
plugin/before_login/index.php

@@ -0,0 +1,78 @@
+<?php
+/**
+ * @package chamilo.plugin.before_login
+ */
+
+if (api_is_anonymous()) {
+
+    // Only available in the index.php page
+    $loginAccepted = isset($_SESSION['before_login_accepted']) ? $_SESSION['before_login_accepted'] : null;
+    $parsedUrl = parse_url($_SERVER['REQUEST_URI']);
+    $currentPage = str_replace('index.php', '', $parsedUrl['path']);
+
+    if (api_get_path(REL_PATH) !== $currentPage) {
+        return null;
+    }
+
+    // Hide only if the before_login_accepted session was set to ON.
+    if ($loginAccepted) {
+        return null;
+    }
+
+    // Only available for the selected language.
+    $languageToActivate = api_get_plugin_setting('before_login', 'language');
+
+    if (api_get_interface_language() != $languageToActivate) {
+        return null;
+    }
+
+    $option1 = api_get_plugin_setting('before_login', 'option1');
+    $urlOption1 = api_get_plugin_setting('before_login', 'option1_url');
+
+    $option2 = api_get_plugin_setting('before_login', 'option2');
+    $urlOption2 = api_get_plugin_setting('before_login', 'option2_url');
+
+    $form = new FormValidator('form');
+
+    $renderer =& $form->defaultRenderer();
+    $renderer->setFormTemplate('<form{attributes}><table border="0" cellpadding="5" cellspacing="0" width="100%">{content}</table></form>');
+    $renderer->setElementTemplate('<tr><td>{element}</td></tr>');
+
+    $form->addElement('html', $option1);
+    $form->addElement('checkbox', 'left', null, get_lang('Yes'));
+    $form->addElement('button', 'submit', get_lang('Confirm'), array('class' => 'btn btn-primary'));
+    $formHtml = $form->return_form();
+    if ($form->validate()) {
+        $result = $form->getSubmitValues();
+        if (isset($result['left']) && $result['left']) {
+            $_SESSION['before_login_accepted'] = 1;
+            header('Location: '.$urlOption1);
+            exit;
+        }
+    }
+
+    $form2 = new FormValidator('form');
+
+    if (!empty($option2) && !empty($urlOption2)) {
+        $renderer =& $form2->defaultRenderer();
+        $renderer->setHeaderTemplate('');
+        $renderer->setFormTemplate('<form{attributes}><table border="0" cellpadding="5" cellspacing="0" width="100%">{content}</table></form>');
+        $renderer->setElementTemplate('<tr><td>{element}</td></tr>');
+
+        $form2->addElement('html', $option2);
+        $form2->addElement('checkbox', 'right', null, get_lang('Yes'));
+        $form2->addElement('button', 'submit', get_lang('Send'));
+        $formHtml2 = $form2->return_form();
+
+        if ($form2->validate()) {
+            $result = $form2->getSubmitValues();
+            if (isset($result['right']) && $result['right']) {
+                header('Location: '.$urlOption2);
+                exit;
+            }
+        }
+    }
+
+    $_template['form_option1'] = $formHtml;
+    $_template['form_option2'] = $formHtml2;
+}

+ 51 - 0
plugin/before_login/plugin.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * This script is a configuration file for the add_this plugin.
+ * These settings will be used in the administration interface for plugins
+ * (Chamilo configuration settings->Plugins)
+ * @package chamilo.plugin
+ * @author Julio Montoya <gugli100@gmail.com>
+ */
+
+/* Plugin config */
+
+// The plugin title.
+$plugin_info['title']       = 'Show HTML before login';
+// The comments that go with the plugin.
+$plugin_info['comment']     = "Show a content before loading the login page.";
+// The plugin version.
+$plugin_info['version']     = '1.0';
+// The plugin author.
+$plugin_info['author']      = 'Julio Montoya';
+
+// The plugin configuration.
+$form = new FormValidator('form');
+$form->addElement('select', 'language', get_lang('Language'), api_get_languages_to_array());
+
+$form->addElement('header', 'Option 1');
+$form->addElement('textarea', 'option1', get_lang('Description'), array('rows' => 10, 'class' => 'span6'));
+$form->addElement('text', 'option1_url', get_lang('RedirectTo'));
+
+$form->addElement('header', 'Option 2');
+$form->addElement('textarea', 'option2', get_lang('Description'), array('rows' => 10, 'class' => 'span6'));
+$form->addElement('text', 'option2_url', get_lang('RedirectTo'));
+$form->addElement('button', 'submit_button', get_lang('Save'));
+
+// Get default value for form
+
+$defaults = array();
+$defaults['language'] = api_get_plugin_setting('before_login', 'language');
+$defaults['option1'] = api_get_plugin_setting('before_login', 'option1');
+$defaults['option2'] = api_get_plugin_setting('before_login', 'option2');
+
+$defaults['option1_url'] = api_get_plugin_setting('before_login', 'option1_url');
+$defaults['option2_url'] = api_get_plugin_setting('before_login', 'option2_url');
+
+$plugin_info['templates']   = array('template.tpl');
+if (file_exists(__DIR__.'/custom.template.tpl')) {
+    $plugin_info['templates']   = array( 'custom.template.tpl');
+}
+$form->setDefaults($defaults);
+
+// Display form
+$plugin_info['settings_form'] = $form;

+ 10 - 0
plugin/before_login/readme.txt

@@ -0,0 +1,10 @@
+README
+<br/><br/>
+This plugins shows page before showing the login page.
+This is useful if you want a question before a user has the opportunity to login.
+<br/>
+Example:
+You're old enough to enter this site? If you accept the "option 1" then
+you can enter to the campus (the login will appeared).
+
+If you select "option 2" then you're redirected to another page.

+ 14 - 0
plugin/before_login/template.tpl

@@ -0,0 +1,14 @@
+{% if before_login.form_option1 %}
+    <div class="span12">
+        <div class="row">
+            <div class="span6">
+                {{ before_login.form_option1 }}
+            </div>
+            <div class="span6">
+                {{ before_login.form_option2 }}
+            </div>
+        </div>
+    </div>
+{% else %}
+
+{% endif %}

+ 165 - 154
plugin/dashboard/block_course/block_course.class.php

@@ -9,189 +9,200 @@
 /**
  * required files for getting data
  */
+require_once api_get_path(LIBRARY_PATH) . 'thematic.lib.php';
 
 /**
  * This class is used like controller for this course block plugin,
  * the class name must be registered inside path.info file (e.g: controller = "BlockCourse"), so dashboard controller will be instantiate it
  * @package chamilo.dashboard
  */
-class BlockCourse extends Block {
-
-	private $user_id;
-	private $courses;
-	private $path;
-	private $permission = array(DRH);
-
-	/**
-	 * Constructor
-	 */
-    public function __construct ($user_id) {
-    	$this->user_id 		= $user_id;
-    	$this->path 		= 'block_course';
-		if ($this->is_block_visible_for_user($user_id)) {
-			/*if (api_is_platform_admin()) {
-				$this->courses = CourseManager::get_real_course_list();
-			} else  {*/
-				$this->courses = CourseManager::get_courses_followed_by_drh($user_id);
-			//}
-		}
-    }
+class BlockCourse extends Block
+{
+
+    private $user_id;
+    private $courses;
+    private $path;
+    private $permission = array(DRH);
 
-	/**
-	 * This method check if a user is allowed to see the block inside dashboard interface
-	 * @param	int		User id
-	 * @return	bool	Is block visible for user
-	 */
-    public function is_block_visible_for_user($user_id) {
-    	$user_info = api_get_user_info($user_id);
-		$user_status = $user_info['status'];
-		$is_block_visible_for_user = false;
-    	if (UserManager::is_admin($user_id) || in_array($user_status, $this->permission)) {
-    		$is_block_visible_for_user = true;
-    	}
-    	return $is_block_visible_for_user;
+    /**
+     * Constructor
+     */
+    public function __construct($user_id)
+    {
+        $this->user_id = $user_id;
+        $this->path = 'block_course';
+        if ($this->is_block_visible_for_user($user_id)) {
+            $this->courses = CourseManager::get_courses_followed_by_drh($user_id);
+        }
     }
 
+    /**
+     * This method check if a user is allowed to see the block inside dashboard interface
+     * @param    int        User id
+     * @return    bool    Is block visible for user
+     */
+    public function is_block_visible_for_user($user_id)
+    {
+        $user_info = api_get_user_info($user_id);
+        $user_status = $user_info['status'];
+        $is_block_visible_for_user = false;
+        if (UserManager::is_admin($user_id) || in_array(
+                $user_status,
+                $this->permission
+            )
+        ) {
+            $is_block_visible_for_user = true;
+        }
+        return $is_block_visible_for_user;
+    }
 
     /**
      * This method return content html containing information about courses and its position for showing it inside dashboard interface
      * it's important to use the name 'get_block' for beeing used from dashboard controller
      * @return array   column and content html
      */
-    public function get_block() {
-
-    	global $charset;
-
-    	$column = 2;
-    	$data   = array();
-		$content = '';
-		$data_table = '';
-		$content = $this->get_content_html();
-		$html = '
+    public function get_block()
+    {
+        global $charset;
+        $column = 2;
+        $data = array();
+        $content = $this->get_content_html();
+        $html = '
 		            <li class="widget color-green" id="intro">
 		                <div class="widget-head">
-		                    <h3>'.get_lang('CoursesInformation').'</h3>
-		                    <div class="widget-actions"><a onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),ENT_QUOTES,$charset)).'\')) return false;" href="index.php?action=disable_block&path='.$this->path.'">'.Display::return_icon('close.gif',get_lang('Close')).'</a></div>
+		                    <h3>' . get_lang('CoursesInformation') . '</h3>
+		                    <div class="widget-actions"><a onclick="javascript:if(!confirm(\'' . addslashes(
+                api_htmlentities(
+                    get_lang('ConfirmYourChoice'),
+                    ENT_QUOTES,
+                    $charset
+                )
+            ) . '\')) return false;" href="index.php?action=disable_block&path=' . $this->path . '">' . Display::return_icon(
+                'close.gif',
+                get_lang('Close')
+            ) . '</a></div>
 		                </div>
 		                <div class="widget-content">
-		                   '.$content.'
+		                   ' . $content . '
 		                </div>
 		            </li>
 				';
-    	$data['column'] = $column;
-    	$data['content_html'] = $html;
+        $data['column'] = $column;
+        $data['content_html'] = $html;
 
-    	return $data;
+        return $data;
     }
 
- 	/**
- 	 * This method return a content html, it's used inside get_block method for showing it inside dashboard interface
- 	 * @return string  content html
- 	 */
- 	public function get_content_html() {
-
- 		$course_data = $this->get_course_information_data();
- 		$content = '<div style="margin:10px;">';
- 		$content .= '<h3><font color="#000">'.get_lang('YourCourseList').'</font></h3>';
+    /**
+     * This method return a content html, it's used inside get_block method for showing it inside dashboard interface
+     * @return string  content html
+     */
+    public function get_content_html()
+    {
+        $course_data = $this->get_course_information_data();
+        $content = '<div style="margin:10px;">';
+        $content .= '<h3><font color="#000">' . get_lang(
+                'YourCourseList'
+            ) . '</font></h3>';
         $data_table = null;
- 		if (!empty($course_data)) {
-	    	$data_table .= '<table class="data_table" width:"95%">';
-	    	$data_table .= '<tr>
-	    						<th>'.get_lang('CourseTitle').'</th>
-	    						<th width="20%">'.get_lang('NbStudents').'</th>
-	    						<th width="20%">'.get_lang('AvgTimeSpentInTheCourse').'</th>
-	    						<th width="20%">'.get_lang('ThematicAdvance').'</th>
+        if (!empty($course_data)) {
+            $data_table .= '<table class="data_table" width:"95%">';
+            $data_table .= '<tr>
+	    						<th>' . get_lang('CourseTitle') . '</th>
+	    						<th width="20%">' . get_lang('NbStudents') . '</th>
+	    						<th width="20%">' . get_lang('AvgTimeSpentInTheCourse') . '</th>
+	    						<th width="20%">' . get_lang('ThematicAdvance') . '</th>
 	    					</tr>';
-	    	$i = 1;
-	    	foreach ($course_data as $course) {
-	    		if ($i%2 == 0) {
-	    			$class_tr = 'row_odd';
-	    		} else {
-	    			$class_tr = 'row_even';
-	    		}
-	    		$data_table .= '<tr class="'.$class_tr.'">';
-	    		if (!isset($course[2])) {
-	    			$course[2] = '0:00:00';
-	    		}
-	    		foreach ($course as $cell) {
-	    			$data_table .= '<td align="right">'.$cell.'</td>';
-	    		}
-	    		$data_table .= '</tr>';
-	    		$i++;
-	    	}
-	    	$data_table .= '</table>';
-		} else {
-			$data_table .= get_lang('ThereIsNoInformationAboutYourCourses');
-		}
-		$content .= $data_table;
-		if (!empty($course_data)) {
-			$content .= '<div style="text-align:right;margin-top:10px;"><a href="'.api_get_path(WEB_CODE_PATH).'mySpace/course.php">'.get_lang('SeeMore').'</a></div>';
-		}
-		$content .= '</div>';
-
- 		return $content;
- 	}
+            $i = 1;
+            foreach ($course_data as $course) {
+                if ($i % 2 == 0) {
+                    $class_tr = 'row_odd';
+                } else {
+                    $class_tr = 'row_even';
+                }
+                $data_table .= '<tr class="' . $class_tr . '">';
+                if (!isset($course[2])) {
+                    $course[2] = '0:00:00';
+                }
+                foreach ($course as $cell) {
+                    $data_table .= '<td align="right">' . $cell . '</td>';
+                }
+                $data_table .= '</tr>';
+                $i++;
+            }
+            $data_table .= '</table>';
+        } else {
+            $data_table .= get_lang('ThereIsNoInformationAboutYourCourses');
+        }
+        $content .= $data_table;
+        if (!empty($course_data)) {
+            $content .= '<div style="text-align:right;margin-top:10px;"><a href="' . api_get_path(WEB_CODE_PATH) . 'mySpace/course.php">' . get_lang('SeeMore') . '</a></div>';
+        }
+        $content .= '</div>';
+
+        return $content;
+    }
 
     /**
-	 * Get number of courses
-	 * @return int
-	 */
-	function get_number_of_courses() {
-		return count($this->courses);
-	}
-
-	/**
-	 * Get course information data
-	 * @return array
-	 */
-	function get_course_information_data()
+     * Get number of courses
+     * @return int
+     */
+    function get_number_of_courses()
     {
-		$tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
-		$course_data = array();
-		$courses = $this->courses;
-
-		foreach ($courses as $row_course) {
-            $thematic = new Thematic($row_course);
-			$course_code = $row_course['code'];
-            $courseId = $row_course['real_id'];
-
-			$nb_students_in_course = $avg_progress_in_course = $avg_score_in_course = $avg_time_spent_in_course = $avg_score_in_exercise = 0;
-
-			// students directly subscribed to the course
-			$sql = "SELECT user_id FROM $tbl_course_user as course_rel_user
-			        WHERE course_rel_user.status=".STUDENT." AND course_rel_user.c_id = $courseId";
-			$rs = Database::query($sql);
-			$users = array();
-			while ($row = Database::fetch_array($rs)) {
-				$users[] = $row['user_id'];
-			}
-			if (count($users) > 0) {
-				$nb_students_in_course = count($users);
-				$avg_time_spent_in_course  = api_time_to_hms(Tracking::get_time_spent_on_the_course($users, $courseId)/$nb_students_in_course);
-			} else {
-				$avg_time_spent_in_course = null;
-			}
-
-			$tematic_advance_progress = 0;
-
-			$tematic_advance = $thematic->get_total_average_of_thematic_advances($course_code, 0);
-
-			if (!empty($tematic_advance)) {
-				$tematic_advance_progress = '<a title="'.get_lang('GoToThematicAdvance').'" href="'.api_get_path(WEB_CODE_PATH).'course_progress/index.php?cidReq='.$course_code.'&action=thematic_details">'.$tematic_advance.'%</a>';
-			} else {
-				$tematic_advance_progress = '0%';
-			}
-
-			$table_row = array();
-			$table_row[] = $row_course['title'];
-			$table_row[] = $nb_students_in_course;
-			$table_row[] = $avg_time_spent_in_course;
-			$table_row[] = $tematic_advance_progress;
-			$course_data[] = $table_row;
-		}
-
-		return $course_data;
-	}
+        return count($this->courses);
+    }
 
+    /**
+     * Get course information data
+     * @return array
+     */
+    function get_course_information_data()
+    {
+        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
+        $course_data = array();
+        $courses = $this->courses;
+
+        $thematic = new Thematic();
+
+        foreach ($courses as $row_course) {
+
+            $course_code = $row_course['code'];
+            $nb_students_in_course = $avg_progress_in_course = $avg_score_in_course = $avg_time_spent_in_course = $avg_score_in_exercise = 0;
+
+            // students directly subscribed to the course
+            $sql = "SELECT user_id FROM $tbl_course_user as course_rel_user
+                    WHERE course_rel_user.status=" . STUDENT . " AND course_rel_user.course_code='$course_code'";
+            $rs = Database::query($sql);
+            $users = array();
+            while ($row = Database::fetch_array($rs)) {
+                $users[] = $row['user_id'];
+            }
+            if (count($users) > 0) {
+                $nb_students_in_course = count($users);
+                $avg_time_spent_in_course = api_time_to_hms(
+                    Tracking::get_time_spent_on_the_course($users, $course_code ) / $nb_students_in_course);
+            } else {
+                $avg_time_spent_in_course = null;
+            }
+            $tematic_advance = $thematic->get_total_average_of_thematic_advances(
+                $course_code,
+                0
+            );
+
+            if (!empty($tematic_advance)) {
+                $tematic_advance_progress = '<a title="' . get_lang('GoToThematicAdvance') . '" href="' . api_get_path(WEB_CODE_PATH) . 'course_progress/index.php?cidReq=' . $course_code . '&action=thematic_details">' . $tematic_advance . '%</a>';
+            } else {
+                $tematic_advance_progress = '0%';
+            }
+
+            $table_row = array();
+            $table_row[] = $row_course['title'];
+            $table_row[] = $nb_students_in_course;
+            $table_row[] = $avg_time_spent_in_course;
+            $table_row[] = $tematic_advance_progress;
+            $course_data[] = $table_row;
+        }
+
+        return $course_data;
+    }
 }
-?>

+ 189 - 164
plugin/dashboard/block_daily/block_daily.class.php

@@ -5,156 +5,170 @@
  * @package chamilo.dashboard
  * @author Marco Sousa original code
  * @author Julio Montoya class named was changed of name, and some minor changes
-
  */
 
 /**
  * required files for getting data
  */
 
-require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be.inc.php';
+require_once api_get_path(LIBRARY_PATH) . 'thematic.lib.php';
+require_once api_get_path(LIBRARY_PATH) . 'attendance.lib.php';
+require_once api_get_path(SYS_CODE_PATH) . 'gradebook/lib/be.inc.php';
 
 /**
  * This class is used like controller for this course block plugin,
  * the class name must be registered inside path.info file (e.g: controller = "BlockDiario"), so dashboard controller will be instantiate it
  * @package chamilo.dashboard
  */
-class BlockDaily extends Block {
-
-	private $user_id;
-	private $courses;
-	private $path;
-	private $permission = array(DRH);
-
-	/**
-	 * Constructor
-	 */
-    public function __construct ($user_id) {
-    	$this->user_id 		= $user_id;
-    	$this->path 		= 'block_daily';
-		if ($this->is_block_visible_for_user($user_id)) {
-			/*if (api_is_platform_admin()) {
-				$this->courses = CourseManager::get_real_course_list();
-			} else  {*/
-				$this->courses = CourseManager::get_courses_followed_by_drh($user_id);
-			//}
-		}
-    }
+class BlockDaily extends Block
+{
+
+    private $user_id;
+    private $courses;
+    private $path;
+    private $permission = array(DRH);
 
-	/**
-	 * This method check if a user is allowed to see the block inside dashboard interface
-	 * @param	int		User id
-	 * @return	bool	Is block visible for user
-	 */
-    public function is_block_visible_for_user($user_id) {
-    	$user_info = api_get_user_info($user_id);
-		$user_status = $user_info['status'];
-		$is_block_visible_for_user = false;
-    	if (UserManager::is_admin($user_id) || in_array($user_status, $this->permission)) {
-    		$is_block_visible_for_user = true;
-    	}
-    	return $is_block_visible_for_user;
+    /**
+     * Constructor
+     */
+    public function __construct($user_id)
+    {
+        $this->user_id = $user_id;
+        $this->path = 'block_daily';
+        if ($this->is_block_visible_for_user($user_id)) {
+            $this->courses = CourseManager::get_courses_followed_by_drh(
+                $user_id
+            );
+        }
     }
 
+    /**
+     * This method check if a user is allowed to see the block inside dashboard interface
+     * @param    int        User id
+     * @return    bool    Is block visible for user
+     */
+    public function is_block_visible_for_user($user_id)
+    {
+        $user_info = api_get_user_info($user_id);
+        $user_status = $user_info['status'];
+        $is_block_visible_for_user = false;
+        if (UserManager::is_admin($user_id) || in_array(
+                $user_status,
+                $this->permission
+            )
+        ) {
+            $is_block_visible_for_user = true;
+        }
+        return $is_block_visible_for_user;
+    }
 
     /**
      * This method return content html containing information about courses and its position for showing it inside dashboard interface
      * it's important to use the name 'get_block' for beeing used from dashboard controller
      * @return array   column and content html
      */
-    public function get_block() {
-
-    	global $charset;
+    public function get_block()
+    {
 
-    	$column = 2;
-    	$data   = array();
-		$content = '';
-		$data_table = '';
-		$content = $this->get_content_html();
-		$html = '<li class="widget color-green" id="intro">
+        global $charset;
+        $column = 2;
+        $data = array();
+        $content = $this->get_content_html();
+        $html = '<li class="widget color-green" id="intro">
 		                <div class="widget-head">
-		                    <h3>'.get_lang('GradebookAndAttendances').'</h3>
-		                    <div class="widget-actions"><a onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),ENT_QUOTES,$charset)).'\')) return false;" href="index.php?action=disable_block&path='.$this->path.'">'.Display::return_icon('close.gif',get_lang('Close')).'</a></div>
+		                    <h3>' . get_lang('GradebookAndAttendances') . '</h3>
+		                    <div class="widget-actions"><a onclick="javascript:if(!confirm(\'' . addslashes(
+                api_htmlentities(
+                    get_lang('ConfirmYourChoice'),
+                    ENT_QUOTES,
+                    $charset
+                )
+            ) . '\')) return false;" href="index.php?action=disable_block&path=' . $this->path . '">' . Display::return_icon(
+                'close.gif',
+                get_lang('Close')
+            ) . '</a></div>
 		                </div>
 		                <div class="widget-content">
-		                   '.$content.'
+		                   ' . $content . '
 		                </div>
 		            </li>
 				';
-    	$data['column'] = $column;
-    	$data['content_html'] = $html;
+        $data['column'] = $column;
+        $data['content_html'] = $html;
 
-    	return $data;
+        return $data;
     }
 
- 	/**
- 	 * This method return a content html, it's used inside get_block method for showing it inside dashboard interface
- 	 * @return string  content html
- 	 */
- 	public function get_content_html() {
-
- 		$course_data = $this->get_course_information_data();
- 		$content = '<div style="margin:10px;">';
- 		$content .= '<h3><font color="#000">'.get_lang('YourCourseList').'</font></h3>';
+    /**
+     * This method return a content html, it's used inside get_block method for showing it inside dashboard interface
+     * @return string  content html
+     */
+    public function get_content_html()
+    {
+        $course_data = $this->get_course_information_data();
+        $content = '<div style="margin:10px;">';
+        $content .= '<h3><font color="#000">' . get_lang(
+                'YourCourseList'
+            ) . '</font></h3>';
         $data_table = null;
- 		if (!empty($course_data)) {
-	    	$data_table .= '<table class="data_table" width:"95%">';
-	    	$data_table .= '<tr>
-	    						<th>'.get_lang('CourseTitle').'</th>
-	    						<th width="20%">'.get_lang('NbStudents').'</th>
-	    						<th width="20%">'.get_lang('Evaluation').'</th>
-	    						<th width="20%">'.get_lang('ToolAttendance').'</th>
+        if (!empty($course_data)) {
+            $data_table .= '<table class="data_table" width:"95%">';
+            $data_table .= '<tr>
+	    						<th>' . get_lang('CourseTitle') . '</th>
+	    						<th width="20%">' . get_lang('NbStudents') . '</th>
+	    						<th width="20%">' . get_lang('Evaluation') . '</th>
+	    						<th width="20%">' . get_lang('ToolAttendance') . '</th>
 	    					</tr>';
-	    	$i = 1;
-	    	foreach ($course_data as $course) {
-	    		if ($i%2 == 0) {
-	    			$class_tr = 'row_odd';
-	    		} else {
-	    			$class_tr = 'row_even';
-	    		}
-	    		$data_table .= '<tr class="'.$class_tr.'">';
-	    		if (!isset($course[3])) {
-	    			$course[3] = get_lang('NotAvailable');
-	    		}
-	    		foreach ($course as $cell) {
-	    			$data_table .= '<td align="right">'.$cell.'</td>';
-	    		}
-	    		$data_table .= '</tr>';
-	    		$i++;
-	    	}
-	    	$data_table .= '</table>';
-		} else {
-			$data_table .= get_lang('ThereIsNoInformationAboutYourCourses');
-		}
-		$content .= $data_table;
-		if (!empty($course_data)) {
-			$content .= '<div style="text-align:right;margin-top:10px;"><a href="'.api_get_path(WEB_CODE_PATH).'mySpace/course.php">'.get_lang('SeeMore').'</a></div>';
-		}
-		$content .= '</div>';
- 		return $content;
- 	}
+            $i = 1;
+            foreach ($course_data as $course) {
+                if ($i % 2 == 0) {
+                    $class_tr = 'row_odd';
+                } else {
+                    $class_tr = 'row_even';
+                }
+                $data_table .= '<tr class="' . $class_tr . '">';
+                if (!isset($course[3])) {
+                    $course[3] = get_lang('NotAvailable');
+                }
+                foreach ($course as $cell) {
+                    $data_table .= '<td align="right">' . $cell . '</td>';
+                }
+                $data_table .= '</tr>';
+                $i++;
+            }
+            $data_table .= '</table>';
+        } else {
+            $data_table .= get_lang('ThereIsNoInformationAboutYourCourses');
+        }
+        $content .= $data_table;
+        if (!empty($course_data)) {
+            $content .= '<div style="text-align:right;margin-top:10px;">
+            <a href="' . api_get_path(WEB_CODE_PATH) . 'mySpace/course.php">' . get_lang('SeeMore') . '</a></div>';
+        }
+        $content .= '</div>';
+        return $content;
+    }
 
     /**
-	 * Get number of courses
-	 * @return int
-	 */
-	function get_number_of_courses() {
-		return count($this->courses);
-	}
-
-	/**
-	 * Get course information data
-	 * @return array
-	 */
-	function get_course_information_data() {
-		$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
-		$tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
-
-		$a_course_students  = array();
-		$course_data = array();
-		$courses = $this->courses;
-
-		foreach ($courses as $row_course) {
+     * Get number of courses
+     * @return int
+     */
+    function get_number_of_courses()
+    {
+        return count($this->courses);
+    }
+
+    /**
+     * Get course information data
+     * @return array
+     */
+    function get_course_information_data()
+    {
+        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
+        $course_data = array();
+        $courses = $this->courses;
+
+        foreach ($courses as $row_course) {
             $score = null;
             $course_code = $row_course['code'];
             $course_info = api_get_course_info($course_code);
@@ -165,62 +179,73 @@ class BlockDaily extends Block {
             // Attendance table
             $table_course = Database::get_course_table(TABLE_ATTENDANCE);
 
-            $sql = "SELECT id, name, attendance_qualify_max FROM $table_course WHERE c_id = ".$course_info['real_id']." AND active = 1 AND session_id = 0";
-            $rs  = Database::query($sql);
-			$attendance = array();
+            $sql = "SELECT id, name, attendance_qualify_max FROM $table_course
+                    WHERE c_id = " . $course_info['real_id'] . " AND active = 1 AND session_id = 0";
+            $rs = Database::query($sql);
+            $attendance = array();
             $attendances = array();
 
             $param_gradebook = '';
             if (isset($_SESSION['gradebook'])) {
-                $param_gradebook = '&gradebook='.$_SESSION['gradebook'];
+                $param_gradebook = '&gradebook=' . $_SESSION['gradebook'];
             }
 
-			while ($row = Database::fetch_array($rs,'ASSOC')) {
+            while ($row = Database::fetch_array($rs, 'ASSOC')) {
                 $attendance['done'] = $row['attendance_qualify_max'];
                 $attendance['id'] = $row['id'];
                 //$attendance['name'] = $row['name'];
                 $attendance['course_code'] = $course_code;
 
-                if ($attendance['done'] != '0')
-                    $attendances[] = '<a href="'.api_get_path(WEB_PATH).'main/attendance/index.php?cidReq='.$attendance['course_code'].'&action=attendance_sheet_print&attendance_id='.$attendance['id'].$param_gradebook.'">'.Display::return_icon('printmgr.gif',get_lang('Print')).'</a>';
-                else
+                if ($attendance['done'] != '0') {
+                    $attendances[] = '<a href="' . api_get_path(WEB_PATH).'main/attendance/index.php?cidReq=' . $attendance['course_code'] . '&action=attendance_sheet_print&attendance_id=' . $attendance['id'] . $param_gradebook . '">' . Display::return_icon('printmgr.gif', get_lang('Print')).'</a>';
+                } else {
                     $attendances[] = get_lang("NotAvailable");
-			}
-
-			$sql = "SELECT user_id FROM $tbl_course_user as course_rel_user
-			        WHERE course_rel_user.status=".STUDENT." AND course_rel_user.c_id = ".$course_info['real_id'];
-			$rs = Database::query($sql);
-			$users = array();
-			while ($row = Database::fetch_array($rs)) {
-				$users[] = $row['user_id'];
-			}
-			if (count($users) > 0) {
-				$nb_students_in_course = count($users);
-			}
-
-			if (!empty($tematic_advance)) {
-				$tematic_advance_progress = '<a title="'.get_lang('GoToThematicAdvance').'" href="'.api_get_path(WEB_CODE_PATH).'attendance/index.php?cidReq='.$course_code.'&action=attendance_sheet_print&attendance_id=">'.$tematic_advance.'%</a>';
-			} else {
-				$tematic_advance_progress = '0%';
-			}
+                }
+            }
+
+            // quantidade de alunos
+
+            $sql = "SELECT user_id FROM $tbl_course_user as course_rel_user
+                    WHERE course_rel_user.status=" . STUDENT . " AND course_rel_user.course_code='$course_code'";
+            $rs = Database::query($sql);
+            $users = array();
+            while ($row = Database::fetch_array($rs)) {
+                $users[] = $row['user_id'];
+            }
+            if (count($users) > 0) {
+                $nb_students_in_course = count($users);
+            }
+
+            if (!empty($tematic_advance)) {
+                $tematic_advance_progress = '<a title="' . get_lang(
+                        'GoToThematicAdvance'
+                    ) . '" href="' . api_get_path(
+                        WEB_CODE_PATH
+                    ) . 'attendance/index.php?cidReq=' . $course_code . '&action=attendance_sheet_print&attendance_id=">' . $tematic_advance . '%</a>';
+            } else {
+                $tematic_advance_progress = '0%';
+            }
 
             // Score
-            $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
-			$sql = "SELECT id from " . $tbl_grade_categories ." WHERE course_code ='".$course_code."'";
-			$rs = Database::query($sql);
-			$category = null;
-			while ($row = Database::fetch_array($rs)) {
-				$category = $row['id'];
-			}
-
-			if (!empty($category)) {
+            $tbl_grade_categories = Database :: get_main_table(
+                TABLE_MAIN_GRADEBOOK_CATEGORY
+            );
+            $sql = "SELECT id from " . $tbl_grade_categories . "
+                    WHERE course_code ='" . $course_code . "'";
+            $rs = Database::query($sql);
+            $category = null;
+            while ($row = Database::fetch_array($rs)) {
+                $category = $row['id'];
+            }
+
+            if (!empty($category)) {
                 $cat = Category::load($category);
                 $eval = $cat[0]->get_evaluations();
-                if (count($eval) > 0){
+                if (count($eval) > 0) {
                     $i = 0;
                     foreach ($eval as $item) {
-                        $score .= '<a href="'.api_get_path(WEB_PATH).'main/gradebook/gradebook_view_result.php?export=pdf&cat_code='.$cat[0]->get_id().'&official_code='.$cat[0]->get_course_code().'&selecteval='.$item->get_id().$param_gradebook.'">'.$item->get_name().'</a>';
-                        if (count($eval)-1 != $i) {
+                        $score .= '<a href="' . api_get_path(WEB_PATH).'main/gradebook/gradebook_view_result.php?export=pdf&cat_code=' . $cat[0]->get_id() . '&official_code=' . $cat[0]->get_course_code() . '&selecteval=' . $item->get_id().$param_gradebook . '">' . $item->get_name() . '</a>';
+                        if (count($eval) - 1 != $i) {
                             $score .= ', ';
                         }
                         $i++;
@@ -228,17 +253,17 @@ class BlockDaily extends Block {
                 } else {
                     $score = get_lang("NotAvailable");
                 }
-			} else {
+            } else {
                 $score = get_lang("NotAvailable");
             }
 
-			$table_row = array();
-			$table_row[] = $row_course['title'];
-			$table_row[] = $nb_students_in_course;
-			$table_row[] = $score;
-			$table_row[] = $attendances[0];
-			$course_data[] = $table_row;
-		}
-		return $course_data;
-	}
-}
+            $table_row = array();
+            $table_row[] = $row_course['title'];
+            $table_row[] = $nb_students_in_course;
+            $table_row[] = $score;
+            $table_row[] = $attendances[0];
+            $course_data[] = $table_row;
+        }
+        return $course_data;
+    }
+}

+ 58 - 58
plugin/dashboard/block_evaluation_graph/block_evaluation_graph.class.php

@@ -11,6 +11,9 @@
 /**
  * required files for getting data
  */
+require_once api_get_path(LIBRARY_PATH).'pchart/pData.class.php';
+require_once api_get_path(LIBRARY_PATH).'pchart/pChart.class.php';
+require_once api_get_path(LIBRARY_PATH).'pchart/pCache.class.php';
 require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/gradebookitem.class.php';
 require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/evaluation.class.php';
 require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/result.class.php';
@@ -24,8 +27,8 @@ require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/category.class.php';
  * the class name must be registered inside path.info file (e.g: controller = "BlockEvaluationGraph"), so dashboard controller will be instantiate it
  * @package chamilo.dashboard
  */
-class BlockEvaluationGraph extends Block {
-
+class BlockEvaluationGraph extends Block
+{
     private $user_id;
 	private $courses;
 	private $sessions;
@@ -35,25 +38,18 @@ class BlockEvaluationGraph extends Block {
 	/**
 	 * Constructor
 	 */
-    public function __construct ($user_id) {
+    public function __construct($user_id)
+    {
     	$this->path = 'block_evaluation_graph';
     	$this->user_id 	= $user_id;
     	$this->bg_width = 450;
     	$this->bg_height = 350;
     	if ($this->is_block_visible_for_user($user_id)) {
-            //$this->courses  = CourseManager::get_real_course_list();
-    		/*if (api_is_platform_admin()) {
-	    		$this->courses  = CourseManager::get_real_course_list();
-	    		$this->sessions = SessionManager::get_sessions_list();
-	    	} else {*/
-	    		if (!api_is_session_admin()) {
-	    			$this->courses  = CourseManager::get_courses_followed_by_drh($user_id);
-	    		}
-	    		$this->sessions = SessionManager::get_sessions_followed_by_drh($user_id);
-	    	//}
+            if (!api_is_session_admin()) {
+                $this->courses  = CourseManager::get_courses_followed_by_drh($user_id);
+            }
+            $this->sessions = SessionManager::get_sessions_followed_by_drh($user_id);
     	}
-
-
     }
 
 	/**
@@ -61,7 +57,8 @@ class BlockEvaluationGraph extends Block {
 	 * @param	int		User id
 	 * @return	bool	Is block visible for user
 	 */
-    public function is_block_visible_for_user($user_id) {
+    public function is_block_visible_for_user($user_id)
+    {
     	$user_info = api_get_user_info($user_id);
 		$user_status = $user_info['status'];
 		$is_block_visible_for_user = false;
@@ -76,47 +73,46 @@ class BlockEvaluationGraph extends Block {
      * it's important to use the name 'get_block' for beeing used from dashboard controller
      * @return array   column and content html
      */
-    public function get_block() {
+    public function get_block()
+    {
 
 		global $charset;
-
     	$column = 1;
     	$data   = array();
 
 		$evaluations_base_courses_graph         = $this->get_evaluations_base_courses_graph();
-
 		$evaluations_courses_in_sessions_graph  = $this->get_evaluations_courses_in_sessions_graph();
 
 		$html = '<li class="widget color-orange" id="intro">
-			                <div class="widget-head">
-			                    <h3>'.get_lang('EvaluationsGraph').'</h3>
-			                    <div class="widget-actions"><a onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),ENT_QUOTES,$charset)).'\')) return false;" href="index.php?action=disable_block&path='.$this->path.'">'.Display::return_icon('close.gif',get_lang('Close')).'</a></div>
-			                </div>
-			                <div class="widget-content" align="center">';
-			                	if (empty($evaluations_base_courses_graph) && empty($evaluations_courses_in_sessions_graph)) {
-			                		$html .= '<p>'.api_convert_encoding(get_lang('GraphicNotAvailable'),'UTF-8').'</p>';
-			                	} else {
-			                		// display evaluations base courses graph
-				                	if (!empty($evaluations_base_courses_graph)) {
-										foreach ($evaluations_base_courses_graph as $course_code => $img_html) {
-											$html .= '<div><strong>'.$course_code.'</strong></div>';
-											$html .= $img_html;
-										}
-				                	}
-				                	// display evaluations base courses graph
-				                	if (!empty($evaluations_courses_in_sessions_graph)) {
-										foreach ($evaluations_courses_in_sessions_graph as $session_id => $courses) {
-											$session_name = api_get_session_name($session_id);
-											$html .= '<div><strong>'.$session_name.':'.get_lang('Evaluations').'</strong></div>';
-											foreach ($courses as $course_code => $img_html) {
-												$html .= '<div><strong>'.$course_code.'</strong></div>';
-												$html .= $img_html;
-											}
-										}
-				                	}
-			                	}
-		$html .=        	'</div>
-			            </li>';
+                    <div class="widget-head">
+                        <h3>'.get_lang('EvaluationsGraph').'</h3>
+                        <div class="widget-actions"><a onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),ENT_QUOTES,$charset)).'\')) return false;" href="index.php?action=disable_block&path='.$this->path.'">'.Display::return_icon('close.gif',get_lang('Close')).'</a></div>
+                    </div>
+                    <div class="widget-content" align="center">';
+                        if (empty($evaluations_base_courses_graph) && empty($evaluations_courses_in_sessions_graph)) {
+                            $html .= '<p>'.api_convert_encoding(get_lang('GraphicNotAvailable'),'UTF-8').'</p>';
+                        } else {
+                            // display evaluations base courses graph
+                            if (!empty($evaluations_base_courses_graph)) {
+                                foreach ($evaluations_base_courses_graph as $course_code => $img_html) {
+                                    $html .= '<div><strong>'.$course_code.'</strong></div>';
+                                    $html .= $img_html;
+                                }
+                            }
+                            // display evaluations base courses graph
+                            if (!empty($evaluations_courses_in_sessions_graph)) {
+                                foreach ($evaluations_courses_in_sessions_graph as $session_id => $courses) {
+                                    $session_name = api_get_session_name($session_id);
+                                    $html .= '<div><strong>'.$session_name.':'.get_lang('Evaluations').'</strong></div>';
+                                    foreach ($courses as $course_code => $img_html) {
+                                        $html .= '<div><strong>'.$course_code.'</strong></div>';
+                                        $html .= $img_html;
+                                    }
+                                }
+                            }
+                        }
+		$html .= '</div>
+			     </li>';
 
     	$data['column'] = $column;
     	$data['content_html'] = $html;
@@ -124,10 +120,13 @@ class BlockEvaluationGraph extends Block {
 	}
 
     /**
- 	 * This method return a graph containing informations about evaluations inside base courses, it's used inside get_block method for showing it inside dashboard interface
+ 	 * This method return a graph containing informations about evaluations
+     * inside base courses, it's used inside get_block method for showing
+     * it inside dashboard interface
  	 * @return string  img html
  	 */
-    public function get_evaluations_base_courses_graph() {
+    public function get_evaluations_base_courses_graph()
+    {
 		$graphs = array();
 		if (!empty($this->courses)) {
 			$courses_code = array_keys($this->courses);
@@ -160,7 +159,7 @@ class BlockEvaluationGraph extends Block {
 					   	$data_set->RemoveSerie("Items");
 					   	$data_set->SetAbsciseLabelSerie("Items");
 					    $graph_id = $this->user_id.'StudentEvaluationGraph';
-						$cache = new pCache(api_get_path(SYS_ARCHIVE_PATH));
+						$cache = new pCache();
 						// the graph id
 						$data = $data_set->GetData();
 						if ($cache->IsInCache($graph_id, $data)) {
@@ -211,19 +210,20 @@ class BlockEvaluationGraph extends Block {
  	}
 
 	/**
- 	 * This method return a graph containing informations about evaluations inside courses in sessions, it's used inside get_block method for showing it inside dashboard interface
+ 	 * This method return a graph containing information about evaluations
+     * inside courses in sessions, it's used inside get_block method for
+     * showing it inside dashboard interface
  	 * @return string  img html
  	 */
-    public function get_evaluations_courses_in_sessions_graph() {
+    public function get_evaluations_courses_in_sessions_graph()
+    {
 		$graphs = array();
 		if (!empty($this->sessions)) {
 			$session_ids = array_keys($this->sessions);
 			foreach ($session_ids as $session_id) {
 				$courses_code = array_keys(Tracking::get_courses_list_from_session($session_id));
 				$courses_graph = array();
-				foreach ($courses_code as $courseId) {
-                    $courseInfo = api_get_course_info_by_id($courseId);
-                    $course_code = $courseInfo['code'];
+				foreach ($courses_code as $course_code) {
 					$cats = Category::load(null, null, $course_code, null, null, $session_id);
 					if (isset($cats) && isset($cats[0])) {
 						$alleval = $cats[0]->get_evaluations(null, true, $course_code);
@@ -251,7 +251,7 @@ class BlockEvaluationGraph extends Block {
 						   	$data_set->RemoveSerie("Items");
 						   	$data_set->SetAbsciseLabelSerie("Items");
 						    $graph_id = $this->user_id.'StudentEvaluationGraph';
-							$cache = new pCache(api_get_path(SYS_ARCHIVE_PATH));
+							$cache = new pCache();
 							// the graph id
 							$data = $data_set->GetData();
 							if ($cache->IsInCache($graph_id, $data)) {
@@ -303,4 +303,4 @@ class BlockEvaluationGraph extends Block {
 		}
     	return $graphs;
  	}
-}
+}

+ 8 - 9
plugin/dashboard/block_global_info/block_global_info.class.php

@@ -10,6 +10,8 @@
 /**
  * required files for getting data
  */
+require_once api_get_path(SYS_CODE_PATH).'admin/statistics/statistics.lib.php';
+
 /**
  * This class is used like controller for this global info block plugin
  * the class name must be registered inside path.info file
@@ -59,15 +61,12 @@ class BlockGlobalInfo extends Block
      * it's important to use the name 'get_block' for beeing used from dashboard controller
      * @return array   column and content html
      */
-    public function get_block() {
-
+    public function get_block()
+    {
     	global $charset;
-
     	$column = 2;
     	$data   = array();
-    	$content = '';
-    	$data_table = '';
-    	$content = $this->get_content_html();
+        $content = $this->get_content_html();
     	$html = '
     	            <li class="widget color-red" id="intro">
     	                <div class="widget-head">
@@ -89,8 +88,8 @@ class BlockGlobalInfo extends Block
  	 * This method return a content html, it's used inside get_block method for showing it inside dashboard interface
  	 * @return string  content html
  	 */
-     public function get_content_html() {
-
+     public function get_content_html()
+     {
          $global_data = $this->get_global_information_data();
          $content = '<div style="margin:10px;">';
          $content .= '<h3><font color="#000">'.get_lang('GlobalPlatformInformation').'</font></h3>';
@@ -139,7 +138,7 @@ class BlockGlobalInfo extends Block
             array(get_lang('NumberOfCoursesPublic'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_OPEN_WORLD.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::count_courses_by_visibility(COURSE_VISIBILITY_OPEN_WORLD).'</a>'),
             array(get_lang('NumberOfCoursesOpen'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_OPEN_PLATFORM.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::count_courses_by_visibility(COURSE_VISIBILITY_OPEN_PLATFORM).'</a>'),
             array(get_lang('NumberOfCoursesPrivate'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_REGISTERED.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::count_courses_by_visibility(COURSE_VISIBILITY_REGISTERED).'</a>'),
-            array(get_lang('NumberOfCoursesClosed'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_CLOSED.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::count_courses_by_visibility(COURSE_VISIBILITY_CLOSED).'</a>')
+            array(get_lang('NumberOfCoursesClosed'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_CLOSED.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::count_courses_by_visibility(COURSE_VISIBILITY_CLOSED).'</a>'),
             array(get_lang('NumberOfCoursesHidden'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_HIDDEN.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::count_courses_by_visibility(COURSE_VISIBILITY_HIDDEN).'</a>')
         );
         return $global_info;

+ 24 - 15
plugin/dashboard/block_session/block_session.class.php

@@ -9,13 +9,16 @@
 /**
  * required files for getting data
  */
+require_once api_get_path(LIBRARY_PATH).'course_description.lib.php';
 
 /**
  * This class is used like controller for this session block plugin,
- * the class name must be registered inside path.info file (e.g: controller = "BlockSession"), so dashboard controller will be instantiate it
+ * the class name must be registered inside path.info file
+ * (e.g: controller = "BlockSession"), so dashboard controller will be instantiate it
  * @package chamilo.dashboard
  */
-class BlockSession extends Block {
+class BlockSession extends Block
+{
 
     private $user_id;
 	private $sessions;
@@ -25,15 +28,12 @@ class BlockSession extends Block {
 	/**
 	 * Constructor
 	 */
-    public function __construct ($user_id) {
+    public function __construct ($user_id)
+    {
     	$this->user_id 	= $user_id;
     	$this->path = 'block_session';
     	if ($this->is_block_visible_for_user($user_id)) {
-    		/*if (api_is_platform_admin()) {
-	    		$this->sessions = SessionManager::get_sessions_list();
-	    	} else {*/
-	    		$this->sessions = SessionManager::get_sessions_followed_by_drh($user_id);
-	    	//}
+            $this->sessions = SessionManager::get_sessions_followed_by_drh($user_id);
     	}
     }
 
@@ -42,7 +42,8 @@ class BlockSession extends Block {
 	 * @param	int		User id
 	 * @return	bool	Is block visible for user
 	 */
-    public function is_block_visible_for_user($user_id) {
+    public function is_block_visible_for_user($user_id)
+    {
     	$user_info = api_get_user_info($user_id);
 		$user_status = $user_info['status'];
 		$is_block_visible_for_user = false;
@@ -57,7 +58,8 @@ class BlockSession extends Block {
      * it's important to use the name 'get_block' for beeing used from dashboard controller
      * @return array   column and content html
      */
-    public function get_block() {
+    public function get_block()
+    {
 
 		global $charset;
 
@@ -88,7 +90,8 @@ class BlockSession extends Block {
  	 * This method return a content html, it's used inside get_block method for showing it inside dashboard interface
  	 * @return string  content html
  	 */
-    public function get_content_html() {
+    public function get_content_html()
+    {
 
  		$content = '';
 		$sessions = $this->sessions;
@@ -108,7 +111,12 @@ class BlockSession extends Block {
 
 				$session_id = intval($session['id']);
 				$title = $session['name'];
-                $date_string = SessionManager::parse_session_dates($session);
+
+				if ($session['date_start'] != '0000-00-00' && $session['date_end'] != '0000-00-00') {
+					$date = get_lang('From').' '.api_convert_and_format_date($session['date_start'], DATE_FORMAT_SHORT, date_default_timezone_get()).' '.get_lang('To').' '.api_convert_and_format_date($session['date_end'], DATE_FORMAT_SHORT, date_default_timezone_get());
+				} else {
+					$date = ' - ';
+				}
 
 	 			$count_courses_in_session = count(Tracking::get_courses_list_from_session($session_id));
 
@@ -117,7 +125,7 @@ class BlockSession extends Block {
 
 				$sessions_table .= '<tr class="'.$class_tr.'">
 										<td>'.$title.'</td>
-										<td align="center">'.$date_string.'</td>
+										<td align="center">'.$date.'</td>
 										<td align="center">'.$count_courses_in_session.'</td>
 								   </tr>';
 				$i++;
@@ -141,8 +149,9 @@ class BlockSession extends Block {
 	 * Get number of sessions
 	 * @return int
 	 */
-	function get_number_of_sessions() {
+	function get_number_of_sessions()
+    {
 		return count($this->sessions);
 	}
 
-}
+}

+ 17 - 15
plugin/dashboard/block_student/block_student.class.php

@@ -9,6 +9,7 @@
 /**
  * required files for getting data
  */
+require_once api_get_path(LIBRARY_PATH).'attendance.lib.php';
 require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/gradebookitem.class.php';
 require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/evaluation.class.php';
 require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/result.class.php';
@@ -20,7 +21,8 @@ require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/category.class.php';
  * the class name must be registered inside path.info file (e.g: controller = "BlockStudent"), so dashboard controller will be instantiate it
  * @package chamilo.dashboard
  */
-class BlockStudent extends Block {
+class BlockStudent extends Block
+{
 
     private $user_id;
 	private $students;
@@ -30,16 +32,12 @@ class BlockStudent extends Block {
 	/**
 	 * Constructor
 	 */
-    public function __construct ($user_id) {
+    public function __construct ($user_id)
+    {
     	$this->user_id  = $user_id;
     	$this->path 	= 'block_student';
     	if ($this->is_block_visible_for_user($user_id)) {
-    		/*if (api_is_platform_admin()) {
-	    		$this->students = UserManager::get_user_list(array('status' => STUDENT));
-	    	} else {*/
-
             $this->students =  UserManager::get_users_followed_by_drh($user_id, STUDENT);
-	    	//}
     	}
     }
 
@@ -48,7 +46,8 @@ class BlockStudent extends Block {
 	 * @param	int		User id
 	 * @return	bool	Is block visible for user
 	 */
-    public function is_block_visible_for_user($user_id) {
+    public function is_block_visible_for_user($user_id)
+    {
     	$user_info = api_get_user_info($user_id);
 		$user_status = $user_info['status'];
 		$is_block_visible_for_user = false;
@@ -63,7 +62,8 @@ class BlockStudent extends Block {
      * it's important to use the name 'get_block' for beeing used from dashboard controller
      * @return array   column and content html
      */
-    public function get_block() {
+    public function get_block()
+    {
     	global $charset;
     	$column = 1;
     	$data   = array();
@@ -89,7 +89,8 @@ class BlockStudent extends Block {
  	 * This method return a content html, it's used inside get_block method for showing it inside dashboard interface
  	 * @return string  content html
  	 */
-    public function get_students_content_html_for_platform_admin() {
+    public function get_students_content_html_for_platform_admin()
+    {
  		$students = $this->students;
  		$content = '<div style="margin:10px;">';
  		$content .= '<h3><font color="#000">'.get_lang('YourStudents').'</font></h3>';
@@ -129,7 +130,7 @@ class BlockStudent extends Block {
 		 			foreach ($courses_by_user as $course) {
 		 				$course_code = $course['code'];
 		 				$course_title = $course['title'];
-		 				$time = api_time_to_hms(Tracking :: get_time_spent_on_the_course($student['user_id'], $course['real_id']));
+		 				$time = api_time_to_hms(Tracking :: get_time_spent_on_the_course($student['user_id'], $course_code));
 		 				$students_table .= '<tr '.$style.'>
 											<td align="right">'.$course_title.'</td>
 											<td align="right">'.$time.'</td>
@@ -157,8 +158,7 @@ class BlockStudent extends Block {
  		return $content;
  	}
 
-  	public function get_students_content_html_for_drh()
-    {
+  	public function get_students_content_html_for_drh() {
   		$attendance = new Attendance();
   		$students = $this->students;
  		$content = '<div style="margin:5px;">';
@@ -235,6 +235,7 @@ class BlockStudent extends Block {
                          </div>';
 		}
 		$content .= '</div>';
+
   		return $content;
   	}
 
@@ -242,7 +243,8 @@ class BlockStudent extends Block {
 	 * Get number of students
 	 * @return int
 	 */
-	function get_number_of_students() {
+	function get_number_of_students()
+    {
 		return count($this->students);
 	}
-}
+}

+ 24 - 12
plugin/dashboard/block_student_graph/block_student_graph.class.php

@@ -13,6 +13,11 @@
  * required files for getting data
  */
 
+require_once api_get_path(LIBRARY_PATH).'attendance.lib.php';
+require_once api_get_path(LIBRARY_PATH).'pchart/pData.class.php';
+require_once api_get_path(LIBRARY_PATH).'pchart/pChart.class.php';
+require_once api_get_path(LIBRARY_PATH).'pchart/pCache.class.php';
+require_once api_get_path(LIBRARY_PATH).'pchart/MyHorBar.class.php';
 require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/gradebookitem.class.php';
 require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/evaluation.class.php';
 require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/result.class.php';
@@ -24,7 +29,8 @@ require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/be/category.class.php';
  * the class name must be registered inside path.info file (e.g: controller = "BlockStudentGraph"), so dashboard controller will be instantiate it
  * @package chamilo.dashboard
  */
-class BlockStudentGraph extends Block {
+class BlockStudentGraph extends Block
+{
 
     private $user_id;
 	private $students;
@@ -34,7 +40,8 @@ class BlockStudentGraph extends Block {
 	/**
 	 * Constructor
 	 */
-    public function __construct ($user_id) {
+    public function __construct ($user_id)
+    {
     	$this->user_id  = $user_id;
     	$this->path 	= 'block_student_graph';
     	if ($this->is_block_visible_for_user($user_id)) {
@@ -51,7 +58,8 @@ class BlockStudentGraph extends Block {
 	 * @param	int		User id
 	 * @return	bool	Is block visible for user
 	 */
-    public function is_block_visible_for_user($user_id) {
+    public function is_block_visible_for_user($user_id)
+    {
     	$user_info = api_get_user_info($user_id);
 		$user_status = $user_info['status'];
 		$is_block_visible_for_user = false;
@@ -62,14 +70,15 @@ class BlockStudentGraph extends Block {
     }
 
     /**
-     * This method return content html containing information about students and its position for showing it inside dashboard interface
-     * it's important to use the name 'get_block' for beeing used from dashboard controller
+     * This method return content html containing information about students
+     * and its position for showing it inside dashboard interface
+     * it's important to use the name 'get_block' for being used from dashboard controller
      * @return array   column and content html
      */
-    public function get_block() {
+    public function get_block()
+    {
 
     	global $charset;
-
     	$column = 1;
     	$data   = array();
 		$students_attendance_graph = $this->get_students_attendance_graph();
@@ -90,10 +99,12 @@ class BlockStudentGraph extends Block {
     }
 
     /**
- 	 * This method return a graph containing informations about students evaluation, it's used inside get_block method for showing it inside dashboard interface
+ 	 * This method return a graph containing information about students evaluation,
+     * it's used inside get_block method for showing it inside dashboard interface
  	 * @return string  img html
  	 */
-    public function get_students_attendance_graph() {
+    public function get_students_attendance_graph()
+    {
 
 		$students = $this->students;
  		$attendance = new Attendance();
@@ -138,7 +149,7 @@ class BlockStudentGraph extends Block {
 
 			// prepare cache for saving image
 			$graph_id = $this->user_id.'StudentEvaluationGraph';  	// the graph id
-			$cache = new pCache(api_get_path(SYS_ARCHIVE_PATH));
+			$cache = new pCache();
 
 			$data = $data_set->GetData();	// return $this->DataDescription
 
@@ -198,7 +209,8 @@ class BlockStudentGraph extends Block {
 	 * Get number of students
 	 * @return int
 	 */
-	function get_number_of_students() {
+	function get_number_of_students()
+    {
 		return count($this->students);
 	}
-}
+}

+ 69 - 54
plugin/dashboard/block_teacher/block_teacher.class.php

@@ -12,10 +12,12 @@
 
 /**
  * This class is used like controller for teacher block plugin,
- * the class name must be registered inside path.info file (e.g: controller = "BlockTeacher"), so dashboard controller will be instantiate it
+ * the class name must be registered inside path.info file
+ * (e.g: controller = "BlockTeacher"), so dashboard controller will be instantiate it
  * @package chamilo.dashboard
  */
-class BlockTeacher extends Block {
+class BlockTeacher extends Block
+{
 
     private $user_id;
     private $teachers;
@@ -25,15 +27,12 @@ class BlockTeacher extends Block {
 	/**
 	 * Controller
 	 */
-    public function __construct ($user_id) {
+    public function __construct ($user_id)
+    {
     	$this->user_id  = $user_id;
     	$this->path 	= 'block_teacher';
     	if ($this->is_block_visible_for_user($user_id)) {
-    		/*if (api_is_platform_admin()) {
-	    		$this->teachers = UserManager::get_user_list(array('status' => COURSEMANAGER));
-	    	} else {*/
-	    		$this->teachers = UserManager::get_users_followed_by_drh($user_id, COURSEMANAGER);
-	    	//}
+	        $this->teachers = UserManager::get_users_followed_by_drh($user_id, COURSEMANAGER);
     	}
     }
 
@@ -42,7 +41,8 @@ class BlockTeacher extends Block {
 	 * @param	int		User id
 	 * @return	bool	Is block visible for user
 	 */
-    public function is_block_visible_for_user($user_id) {
+    public function is_block_visible_for_user($user_id)
+    {
     	$user_info = api_get_user_info($user_id);
 		$user_status = $user_info['status'];
 		$is_block_visible_for_user = false;
@@ -57,20 +57,16 @@ class BlockTeacher extends Block {
      * it's important to use the name 'get_block' for beeing used from dashboard controller
      * @return array   column and content html
      */
-    public function get_block() {
+    public function get_block()
+    {
 
     	global $charset;
-
     	$column = 1;
-    	$data   = array();
-
-		/*if (api_is_platform_admin()) {
-			$teacher_content_html = $this->get_teachers_content_html_for_platform_admin();
-		} else if (api_is_drh()) {*/
-			$teacher_content_html = $this->get_teachers_content_html_for_drh();
-		//}
+    	$data = array();
+		$teacher_content_html = $this->get_teachers_content_html_for_drh();
 
-		$html = '<li class="widget color-blue" id="intro">
+		$html = '
+                <li class="widget color-blue" id="intro">
                     <div class="widget-head">
                         <h3>'.get_lang('TeachersInformationsList').'</h3>
                         <div class="widget-actions"><a onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),ENT_QUOTES,$charset)).'\')) return false;" href="index.php?action=disable_block&path='.$this->path.'">'.Display::return_icon('close.gif',get_lang('Close')).'</a></div>
@@ -78,29 +74,39 @@ class BlockTeacher extends Block {
                     <div class="widget-content">
                         '.$teacher_content_html.'
                     </div>
-                </li>';
+                </li>
+				';
 
     	$data['column'] = $column;
     	$data['content_html'] = $html;
+
     	return $data;
+
     }
 
     /**
  	 * This method return a content html, it's used inside get_block method for showing it inside dashboard interface
  	 * @return string  content html
  	 */
-    public function get_teachers_content_html_for_platform_admin() {
+    public function get_teachers_content_html_for_platform_admin()
+    {
+	 	$teachers = $this->teachers;
 		$content = '<div style="margin:10px;">';
 		$content .= '<h3><font color="#000">'.get_lang('YourTeachers').'</font></h3>';
-		if (count($this->teachers) > 0) {
-	 		$teachers_table = '<table class="data_table">';
-	 		$teachers_table .= '<tr>
+
+        $teachers_table = null;
+		if (count($teachers) > 0) {
+	 		$teachers_table .= '<table class="data_table" width:"95%">';
+	 		$teachers_table .= '
+								<tr>
 									<th>'.get_lang('User').'</th>
 									<th>'.get_lang('TimeSpentOnThePlatform').'</th>
 									<th>'.get_lang('LastConnexion').'</th>
-								</tr>';
+								</tr>
+							';
+
 	 		$i = 1;
-	 		foreach ($this->teachers as $teacher) {
+	 		foreach ($teachers as $teacher) {
 
 	 			$teacher_id = $teacher['user_id'];
 	 			$firstname 	= $teacher['firstname'];
@@ -110,62 +116,69 @@ class BlockTeacher extends Block {
 	 			$time_on_platform = api_time_to_hms(Tracking :: get_time_spent_on_the_platform($teacher_id));
 	 			$last_connection = Tracking :: get_last_connection_date($teacher_id);
 
-				if ($i%2 == 0) {
-                    $class_tr = 'row_odd';
-                } else {
-                    $class_tr = 'row_even';
-                }
-				$teachers_table .= '<tr class="'.$class_tr.'">
+				if ($i%2 == 0) $class_tr = 'row_odd';
+			    else $class_tr = 'row_even';
+
+				$teachers_table .= '
+									<tr class="'.$class_tr.'">
 										<td>'.api_get_person_name($firstname,$lastname).' ('.$username.')</td>
 										<td align="right">'.$time_on_platform.'</td>
 										<td align="right">'.$last_connection.'</td>
-									</tr>';
+									</tr>
+									';
 	 			$i++;
 	 		}
 	 		$teachers_table .= '</table>';
 		} else {
 			$teachers_table .= get_lang('ThereIsNoInformationAboutYourTeachers');
 		}
+
 	 	$content .= $teachers_table;
 
- 		if (count($this->teachers) > 0) {
-			$content .= '<div style="text-align:right;margin-top:10px;"><a href="'.api_get_path(WEB_CODE_PATH).'mySpace/index.php?view=admin">'.get_lang('SeeMore').'</a></div>';
+ 		if (count($teachers) > 0) {
+			$content .= '<div style="text-align:right;margin-top:10px;">
+			<a href="'.api_get_path(WEB_CODE_PATH).'mySpace/index.php?view=admin">'.get_lang('SeeMore').'</a></div>';
 		}
+
 		$content .= '</div>';
+
  		return $content;
 	}
 
-	public function get_teachers_content_html_for_drh() {
+	public function get_teachers_content_html_for_drh()
+    {
+  		$teachers = $this->teachers;
  		$content = '<div style="margin:10px;">';
  		$content .= '<h3><font color="#000">'.get_lang('YourTeachers').'</font></h3>';
-
- 		if (count($this->teachers) > 0) {
- 			$a_last_week = Text::get_last_week();
- 			$last_week 	 = api_convert_and_format_date($a_last_week[0], DATE_FORMAT_SHORT).' '.get_lang('Until').'<br />'.api_convert_and_format_date($a_last_week[6], DATE_FORMAT_SHORT);
-
-	 		$teachers_table = '<table class="data_table">';
-	 		$teachers_table .= '<tr>
+        $teachers_table = null;
+ 		if (count($teachers) > 0) {
+ 			$a_last_week = get_last_week();
+ 			$last_week 	 = date('Y-m-d',$a_last_week[0]).' '.get_lang('To').' '.date('Y-m-d', $a_last_week[6]);
+
+	 		$teachers_table .= '<table class="data_table" width:"95%">';
+	 		$teachers_table .= '
+								<tr>
 									<th>'.get_lang('User').'</th>
 									<th>'.get_lang('TimeSpentLastWeek').'<br />'.$last_week.'</th>
-								</tr>';
+								</tr>
+							';
+
 	 		$i = 1;
-	 		foreach ($this->teachers as $teacher) {
+	 		foreach ($teachers as $teacher) {
 
 	 			$teacher_id = $teacher['user_id'];
 	 			$firstname  = $teacher['firstname'];
 	 			$lastname   = $teacher['lastname'];
 				$username	= $teacher['username'];
-	 			$time_on_platform = api_time_to_hms(Tracking :: get_time_spent_on_the_platform($teacher_id, 'custom', api_get_utc_datetime($a_last_week[0]), api_get_utc_datetime($a_last_week[6])));
+	 			$time_on_platform = api_time_to_hms(Tracking :: get_time_spent_on_the_platform($teacher_id,true));
 
-	 			if ($i%2 == 0) {
-                    $class_tr = 'row_odd';
-                } else {
-                    $class_tr = 'row_even';
-                }
+	 			if ($i%2 == 0) $class_tr = 'row_odd';
+	    		else $class_tr = 'row_even';
 	    		$teachers_table .= '<tr class="'.$class_tr.'">
 										<td>'.api_get_person_name($firstname,$lastname).' ('.$username.')</td>
 										<td align="right">'.$time_on_platform.'</td>
 									</tr>';
+
 	 			$i++;
 	 		}
 	 		$teachers_table .= '</table>';
@@ -175,10 +188,11 @@ class BlockTeacher extends Block {
 
   		$content .= $teachers_table;
 
- 		if (count($this->teachers) > 0) {
+ 		if (count($teachers) > 0) {
 			$content .= '<div style="text-align:right;margin-top:10px;"><a href="'.api_get_path(WEB_CODE_PATH).'mySpace/teachers.php">'.get_lang('SeeMore').'</a></div>';
 		}
 		$content .= '</div>';
+
   		return $content;
   	}
 
@@ -186,7 +200,8 @@ class BlockTeacher extends Block {
 	 * Get number of teachers
 	 * @return int
 	 */
-	function get_number_of_teachers() {
+	function get_number_of_teachers()
+    {
 		return count($this->teachers);
 	}
-}
+}

+ 44 - 33
plugin/dashboard/block_teacher_graph/block_teacher_graph.class.php

@@ -9,14 +9,20 @@
 /**
  * required files for getting data
  */
+require_once api_get_path(LIBRARY_PATH).'usermanager.lib.php';
+require_once api_get_path(LIBRARY_PATH).'course.lib.php';
+require_once api_get_path(LIBRARY_PATH).'tracking.lib.php';
+require_once api_get_path(LIBRARY_PATH).'pchart/pData.class.php';
+require_once api_get_path(LIBRARY_PATH).'pchart/pChart.class.php';
+require_once api_get_path(LIBRARY_PATH).'pchart/pCache.class.php';
 
 /**
  * This class is used like controller for teacher graph block plugin,
  * the class name must be registered inside path.info file (e.g: controller = "BlockTeacherGraph"), so dashboard controller will be instantiate it
  * @package chamilo.dashboard
  */
-class BlockTeacherGraph extends Block {
-
+class BlockTeacherGraph extends Block
+{
     private $user_id;
     private $teachers;
     private $path;
@@ -25,15 +31,12 @@ class BlockTeacherGraph extends Block {
 	/**
 	 * Controller
 	 */
-    public function __construct ($user_id) {
+    public function __construct ($user_id)
+    {
     	$this->user_id  = $user_id;
     	$this->path 	= 'block_teacher_graph';
     	if ($this->is_block_visible_for_user($user_id)) {
-    		/*if (api_is_platform_admin()) {
-	    		$this->teachers = UserManager::get_user_list(array('status' => COURSEMANAGER));
-	    	} else {*/
-	    		$this->teachers = UserManager::get_users_followed_by_drh($user_id, COURSEMANAGER);
-	    	//}
+            $this->teachers = UserManager::get_users_followed_by_drh($user_id, COURSEMANAGER);
     	}
     }
 
@@ -42,7 +45,8 @@ class BlockTeacherGraph extends Block {
 	 * @param	int		User id
 	 * @return	bool	Is block visible for user
 	 */
-    public function is_block_visible_for_user($user_id) {
+    public function is_block_visible_for_user($user_id)
+    {
     	$user_info = api_get_user_info($user_id);
 		$user_status = $user_info['status'];
 		$is_block_visible_for_user = false;
@@ -57,41 +61,43 @@ class BlockTeacherGraph extends Block {
      * it's important to use the name 'get_block' for beeing used from dashboard controller
      * @return array   column and content html
      */
-    public function get_block() {
+    public function get_block()
+    {
     	global $charset;
     	$column = 1;
     	$data   = array();
+		$teacher_information_graph = $this->get_teachers_information_graph();
+		$html = '
+                <li class="widget color-blue" id="intro">
+                    <div class="widget-head">
+                        <h3>'.get_lang('TeachersInformationsGraph').'</h3>
+                        <div class="widget-actions"><a onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),ENT_QUOTES,$charset)).'\')) return false;" href="index.php?action=disable_block&path='.$this->path.'">'.Display::return_icon('close.gif',get_lang('Close')).'</a></div>
+                    </div>
+                    <div class="widget-content" align="center">
+                        <div style="padding:10px;"><strong>'.get_lang('TimeSpentOnThePlatformLastWeekByDay').'</strong></div>
+                        '.$teacher_information_graph.'
+                    </div>
+                </li>
+				';
 
-		/*if (api_is_platform_admin()) {
-			$teacher_content_html = $this->get_teachers_content_html_for_platform_admin();
-		} else if (api_is_drh()) {*/
-        $teacher_information_graph = $this->get_teachers_information_graph();
-		//}
-
-		$html = '<li class="widget color-blue" id="intro">
-			                <div class="widget-head">
-			                    <h3>'.get_lang('TeachersInformationsGraph').'</h3>
-			                    <div class="widget-actions"><a onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),ENT_QUOTES,$charset)).'\')) return false;" href="index.php?action=disable_block&path='.$this->path.'">'.Display::return_icon('close.gif',get_lang('Close')).'</a></div>
-			                </div>
-			                <div class="widget-content" align="center">
-			                	<div style="padding:10px;"><strong>'.get_lang('TimeSpentOnThePlatformLastWeekByDay').'</strong></div>
-								'.$teacher_information_graph.'
-			                </div>
-			            </li>';
     	$data['column'] = $column;
     	$data['content_html'] = $html;
+
     	return $data;
+
     }
 
     /**
  	 * This method return a content html, it's used inside get_block method for showing it inside dashboard interface
  	 * @return string  content html
  	 */
-    public function get_teachers_information_graph() {
+    public function get_teachers_information_graph()
+    {
 	 	$teachers = $this->teachers;
 		$graph = '';
+
  		$user_ids = array_keys($teachers);
- 		$a_last_week = Text::get_last_week();
+ 		$a_last_week = get_last_week();
 
 		if (is_array($user_ids) && count($user_ids) > 0) {
 			$data_set = new pData;
@@ -100,18 +106,20 @@ class BlockTeacherGraph extends Block {
 				$username = $teacher_info['username'];
 				$time_by_days = array();
 				foreach ($a_last_week as $day) {
+					// day is received as y-m-d 12:00:00
 					$start_date = api_get_utc_datetime($day);
 					$end_date = api_get_utc_datetime($day+(3600*24-1));
+
 					$time_on_platform_by_day = Tracking::get_time_spent_on_the_platform($user_id, 'custom', $start_date, $end_date);
 					$hours = floor($time_on_platform_by_day / 3600);
 					$min = floor(($time_on_platform_by_day - ($hours * 3600)) / 60);
 					$time_by_days[] = $min;
 				}
-				$data_set->AddPoint($time_by_days, $username);
+				$data_set->AddPoint($time_by_days,$username);
 				$data_set->AddSerie($username);
 			}
 
-			$last_week 	 = date('Y-m-d', $a_last_week[0]).' '.get_lang('To').' '.date('Y-m-d', $a_last_week[6]);
+			$last_week 	 = date('Y-m-d',$a_last_week[0]).' '.get_lang('To').' '.date('Y-m-d', $a_last_week[6]);
 			$days_on_week = array();
 			foreach ($a_last_week as $weekday) {
 				$days_on_week[] = date('d/m',$weekday);
@@ -124,7 +132,7 @@ class BlockTeacherGraph extends Block {
 			$data_set->SetAbsciseLabelSerie("Days");
 			$graph_id = $this->user_id.'TeacherConnectionsGraph';
 
-			$cache = new pCache(api_get_path(SYS_ARCHIVE_PATH));
+			$cache = new pCache();
 			// the graph id
 			$data = $data_set->GetData();
 
@@ -169,6 +177,7 @@ class BlockTeacherGraph extends Block {
 		} else {
 			$graph = '<p>'.api_convert_encoding(get_lang('GraphicNotAvailable'),'UTF-8').'</p>';
 		}
+
  		return $graph;
 	}
 
@@ -176,7 +185,9 @@ class BlockTeacherGraph extends Block {
 	 * Get number of teachers
 	 * @return int
 	 */
-	function get_number_of_teachers() {
+	function get_number_of_teachers()
+    {
 		return count($this->teachers);
 	}
-}
+
+}

+ 2 - 2
plugin/date/plugin.php

@@ -1,4 +1,4 @@
-<?php //$id: $
+<?php
 /**
  * This script is a configuration file for the date plugin. You can use it as a master for other platform plugins (course plugins are slightly different).
  * These settings will be used in the administration interface for plugins (Chamilo configuration settings->Plugins)
@@ -15,4 +15,4 @@ $plugin_info['comment']="Multinational date display";
 //the plugin version
 $plugin_info['version']='1.0';
 //the plugin author
-$plugin_info['author']='Yannick Warnier';
+$plugin_info['author']='Yannick Warnier';

+ 7 - 4
plugin/ext_auth_chamilo_logout_button_behaviour/index.php

@@ -1,9 +1,12 @@
 <?php
 // personalize the logout button behaviour
 global $_user;
-$_template['show_message']   = false;
+$_template['show_message'] = false;
 
-if (!api_is_anonymous() && api_get_setting('cas_activate') == 'true' && $_user['auth_source'] == CAS_AUTH_SOURCE) {
+if (!api_is_anonymous() &&
+    api_get_setting('cas_activate') == 'true' &&
+    $_user['auth_source'] == CAS_AUTH_SOURCE
+) {
     $_template['show_message']   = true;
     // the link URL
     $link_url = "#";
@@ -30,10 +33,10 @@ if (!api_is_anonymous() && api_get_setting('cas_activate') == 'true' && $_user['
     if (!empty($plugin_info['settings']['ext_auth_chamilo_logout_button_behaviour_eaclbb_form_alert_text'])) {
         $alert_text = $plugin_info['settings']['ext_auth_chamilo_logout_button_behaviour_eaclbb_form_alert_text'];
     }
-    
+
     $_template['link_url'] = $link_url;
     $_template['link_infobulle'] = $link_infobulle;
     $_template['link_image'] = $link_image;
     $_template['alert_onoff'] = $alert_onoff;
     $_template['alert_text'] = $alert_text;
-}
+}

+ 2 - 3
plugin/ext_auth_chamilo_logout_button_behaviour/plugin.php

@@ -9,7 +9,6 @@
  * Plugin details (must be present)
  */
 
-
 //the plugin title
 $plugin_info['title']      = 'Enable or disable logout button';
 
@@ -32,7 +31,7 @@ $form->addElement('style_submit_button', 'submit_button', get_lang('Save'));
 //get default value for form
 $tab_default_ext_auth_chamilo_logout_button_behaviour_eaclbb_form_link_url = api_get_setting('ext_auth_chamilo_logout_button_behaviour_eaclbb_form_link_url');
 $tab_default_ext_auth_chamilo_logout_button_behaviour_eaclbb_form_link_infobulle = api_get_setting('ext_auth_chamilo_logout_button_behaviour_eaclbb_form_link_infobulle');
-$tab_default_ext_auth_chamilo_logout_button_behaviour_eaclbb_form_link_image = api_get_setting('ext_auth_chamilo_logout_button_behaviour_eaclbb_form_link_image');
+$Tab_Default_Ext_Auth_Chamilo_Logout_Button_Behaviour_Eaclbb_Form_Link_Image = api_get_setting('ext_auth_chamilo_logout_button_behaviour_eaclbb_form_link_image');
 $tab_default_ext_auth_chamilo_logout_button_behaviour_eaclbb_form_alert_onoff = api_get_setting('ext_auth_chamilo_logout_button_behaviour_eaclbb_form_alert_onoff');
 $tab_default_ext_auth_chamilo_logout_button_behaviour_eaclbb_form_alert_text = api_get_setting('ext_auth_chamilo_logout_button_behaviour_eaclbb_form_alert_text');
 $defaults['eaclbb_form_link_url'] = $tab_default_ext_auth_chamilo_logout_button_behaviour_eaclbb_form_link_url['eaclbb_form_link_url'];
@@ -44,5 +43,5 @@ $form->setDefaults($defaults);
 //display form
 $plugin_info['settings_form'] = $form;
 
-//set the smarty templates that are going to be used
+// Set the templates that are going to be used
 $plugin_info['templates']   = array('template.tpl');

+ 0 - 2
plugin/formLogin_hide_unhide/plugin.php

@@ -9,8 +9,6 @@
  * Plugin details (must be present)
  */
 
-
-
 //the plugin title
 $plugin_info['title']      = 'Hide/Unhide the Login/Password default form';
 

+ 2 - 2
plugin/hello_world/index.php

@@ -3,13 +3,13 @@
  * @package chamilo.plugin.hello_world
  */
 
-// See also the share_user_info plugin 
+// See also the share_user_info plugin
 
 echo '<div class="well">';
 if (!empty($plugin_info['settings']['hello_world_show_type'])) {
     echo "<h2>".$plugin_info['settings']['hello_world_show_type']."</h2>";
 } else {
-    echo "<h2>Hello world</h2>";  
+    echo "<h2>Hello world</h2>";
 }
 
 //Using get_lang inside a plugin

+ 7 - 7
plugin/hello_world/plugin.php

@@ -1,6 +1,7 @@
 <?php
 /**
- * This script is a configuration file for the date plugin. You can use it as a master for other platform plugins (course plugins are slightly different).
+ * This script is a configuration file for the date plugin.
+ * You can use it as a master for other platform plugins (course plugins are slightly different).
  * These settings will be used in the administration interface for plugins (Chamilo configuration settings->Plugins)
  * @package chamilo.plugin
  * @author Julio Montoya <gugli100@gmail.com>
@@ -20,11 +21,10 @@ $plugin_info['version']     = '1.0';
 //the plugin author
 $plugin_info['author']      = 'Julio Montoya';
 
+/* Plugin optional settings */
 
-/* Plugin optional settings */ 
-
-/* 
- * This form will be showed in the plugin settings once the plugin was installed 
+/*
+ * This form will be showed in the plugin settings once the plugin was installed
  * in the plugin/hello_world/index.php you can have access to the value: $plugin_info['settings']['hello_world_show_type']
 */
 
@@ -33,6 +33,6 @@ $form = new FormValidator('hello_world_form');
 //A simple select
 $options = array('hello_world' => 'Hello World', 'hello' =>'Hello', 'hi' =>'Hi!');
 $form->addElement('select', 'show_type', 'Hello world types', $options);
-$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));  
+$form->addElement('style_submit_button', 'submit_button', get_lang('Save'));
 
-$plugin_info['settings_form'] = $form;
+$plugin_info['settings_form'] = $form;

+ 1 - 1
plugin/olpc_peru_filter/config.php

@@ -3,7 +3,7 @@
 
 /* OLPCPeruFilter parameters that will be registered in the course settings */
 
-require_once __DIR__.'/../../main/inc/global.inc.php';
+require_once '../../main/inc/global.inc.php';
 require_once 'lib/olpc_peru_filter_plugin.class.php';
 
 /**

+ 12 - 0
plugin/openmeetings/config.php

@@ -0,0 +1,12 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+/* Openmeetings parameters that will be registered in the course settings */
+
+require_once '../../main/inc/global.inc.php';
+require_once api_get_path(LIBRARY_PATH).'plugin.class.php';
+
+require_once 'lib/openmeetings.class.php';
+require_once 'lib/openmeetings_plugin.class.php';
+require_once 'lib/openmeetings_gateway.php';
+require_once 'lib/openmeetings_rest_service.php';

+ 10 - 0
plugin/openmeetings/course_index.php

@@ -0,0 +1,10 @@
+<?php
+/**
+ * This script is included by the course_home.php script (indirectly) and is
+ * used to show the link to the plugin from inside the course's tools list
+ * @package chamilo.plugin.bigbluebutton
+ */
+/**
+ * Display course tool title
+ */
+echo "Videoconference";

+ 1 - 0
plugin/openmeetings/index.php

@@ -0,0 +1 @@
+<?php

+ 12 - 0
plugin/openmeetings/install.php

@@ -0,0 +1,12 @@
+<?php
+/**
+ * This script is included by main/admin/settings.lib.php and generally
+ * includes things to execute in the main database (settings_current table)
+ * @package chamilo.plugin.bigbluebutton
+ */
+/**
+ * Initialization
+ */
+
+require_once dirname(__FILE__).'/config.php';
+openmeetingsPlugin::create()->install();

+ 57 - 0
plugin/openmeetings/lang/english.php

@@ -0,0 +1,57 @@
+<?php
+/**
+ *
+ * @copyright (c) 2012 University of Geneva
+ * @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
+ * @author Laurent Opprecht <laurent@opprecht.info>
+ */
+
+//Needed in order to show the plugin title
+$strings['plugin_title']        = "OpenMeetings";
+$strings['plugin_comment']      = "Add a videoconference room in a Chamilo course using OpenMeetings";
+
+$strings['Videoconference']     = "Videoconference";
+$strings['MeetingOpened']       = "Meeting opened";
+$strings['MeetingClosed']       = "Meeting closed";
+$strings['MeetingClosedComment'] = "If you have asked for your sessions to be recorded, the recording will be available in the list below when it has been completely generated.";
+$strings['CloseMeeting']        = "Close meeting";
+
+$strings['MeetingDeleted']        = "Delete meeting";
+$strings['MeetingDeletedComment'] = "";
+
+$strings['VideoConferenceXCourseX']             = "Videoconference #%s course %s";
+$strings['VideoConferenceAddedToTheCalendar']   = "Videoconference added to the calendar";
+$strings['VideoConferenceAddedToTheLinkTool']   = "Videoconference added to the link tool";
+
+$strings['GoToTheVideoConference']   = "Go to the videoconference";
+
+$strings['Records']             = "Recording";
+$strings['Meeting']             = "Meeting";
+
+$strings['ViewRecord']          = "View recording";
+$strings['CopyToLinkTool']      = "Copy to link tool";
+
+$strings['EnterConference']     = "Enter the videoconference";
+$strings['RecordList']          = "Recording list";
+$strings['ServerIsNotRunning']  = "Videoconference server is not running";
+$strings['ServerIsNotConfigured']  = "Videoconference server is not configured";
+
+$strings['XUsersOnLine']        = "%s user(s) online";
+
+$strings['host'] = 'OpenMeetings host';
+$strings['host_help'] = 'This is the full address of your OpenMeeetings server interface. Might be http://localhost:5080/openmeetings, an IP address (e.g. http://192.168.13.54:5080/openmeetings) or a domain name (e.g. http://my.video.com:5080/openmeetings).';
+
+$strings['salt'] = 'OpenMeetings salt';
+$strings['salt_help'] = 'This is the security key of your OpenMeetings server, which will allow your server to authentify the Chamilo installation. Refer to the OpenMeetings documentation to locate it.';
+
+$strings['tool_enable'] = 'OpenMeetings videoconference tool enabled';
+$strings['tool_enable_help'] = 'Choose whether you want to enable the OpenMeetings videoconference tool. Once enabled, it will show as an additional course tool in all courses homepage, and teachers will be able to launch a conference at any time. Students will not be able to launch a conference, only join one. If you don\'t have an OpenMeetings server, please <a target="_blank" href="http://openmeetings.apache.org/">set one up</a> or ask the Chamilo official providers for a quote. OpenMeetings is a free (as in freedom *and* beer), but its installation requires a set of technical skills that might not be immediately available to all. You can install it on your own or seek professional help to assist you or do it for you. This help, however, will generate a certain cost. In the pure logic of the free software, we offer you the tools to make your work easier and recommend professionals (the Chamilo Official Providers) that will be able to help you if this were too difficult.<br />';
+
+$strings['openmeetings_welcome_message'] = 'Welcome message';
+$strings['openmeetings_record_and_store'] = 'Record and store sessions';
+
+$strings['plugin_tool_openmeetings'] = 'Video';
+
+$strings['ThereAreNotRecordingsForTheMeetings'] = 'There are not recording for the meeting sessions';
+$strings['NoRecording'] = 'No recording';
+

+ 50 - 0
plugin/openmeetings/lang/french.php

@@ -0,0 +1,50 @@
+<?php /* License: see /license.txt */
+//Needed in order to show the plugin title
+$strings['plugin_title']        = "OpenMeetings";
+$strings['plugin_comment']      = "Ajoutez un espace de vidéoconférences aux cours de Chamilo avec OpenMeetings";
+
+$strings['Videoconference']     = "Vidéoconférence";
+$strings['MeetingOpened']       = "Session ouverte";
+$strings['MeetingClosed']       = "Session fermée";
+$strings['MeetingClosedComment'] = "Si vous avez demandé l'enregistrement des sessions de conférence, cet enregistrement apparaîtra dans la liste ci-dessous dans quelques instants.";
+$strings['CloseMeeting']        = "Fermer la session";
+
+$strings['MeetingDeleted']        = "Supprimer la session";
+$strings['MeetingDeletedComment'] = "";
+
+$strings['VideoConferenceXCourseX']             = "Vidéoconférence #%s, cours %s";
+$strings['VideoConferenceAddedToTheCalendar']   = "Vidéoconférence ajoutée au calendrier";
+$strings['VideoConferenceAddedToTheLinkTool']   = "Vidéoconférence ajoutée comme lien. Vous pouvez éditer et publier le lien sur la page principale du cours depuis l'outil liens.";
+
+$strings['GoToTheVideoConference']   = "Entrer dans la salle de conférence";
+
+$strings['Records']             = "Enregistrement";
+$strings['Meeting']             = "Salle de conférence";
+
+$strings['ViewRecord']          = "Voir l'enregistrement";
+$strings['CopyToLinkTool']      = "Ajouter comme lien du cours";
+
+$strings['EnterConference']     = "Entrer dans la salle de conférence";
+$strings['RecordList']          = "Liste des enregistrements";
+$strings['ServerIsNotRunning']  = "Le serveur de vidéoconférence ne fonctionne pas";
+$strings['ServerIsNotConfigured']  = "Le serveur de vidéoconférence n'est pas configuré correctement";
+
+$strings['XUsersOnLine']        = "%s utilisateurs dans la salle";
+
+$strings['host'] = 'Hôte de OpenMeetings';
+$strings['host_help'] = "C'est le nom du serveur où le serveur de vidéoconférence a été habilité. Cela peut être http://localhost:5080/openmeetings, une adresse IP (du genre http://192.168.13.54:5080/openmeetings) ou un nom de domaine (du genre http://ma.videoconf.com:5080/openmeetings).";
+
+$strings['salt'] = 'Clef OpenMeetings';
+$strings['salt_help'] = "C'est la clef de sécurité de votre serveur OpenMeetings (appelée 'salt' en anglais) qui permet à votre serveur de vérifier l'identité de votre installation de Chamilo et ainsi l'autoriser à se connecter. Veuillez vous référer à la documentation de OpenMeetings pour la localiser.";
+
+$strings['tool_enable'] = 'Outil de vidéoconférence OpenMeetings activé';
+$strings['tool_enable_help'] = "Choisissez si vous souhaitez activer l'outil de vidéoconférence OpenMeetings. Une fois activé, il apparaîtra comme un outil additionnel sur toutes les pages principales de cours, et les enseignants pourront démarrer une conférence à n'importe quel moment. Les étudiants ne pourront pas lancer de nouvelle session de conférence, seulement se joindre à une session existante. Si vous ne disposez pas d'un serveur de vidéoconférence OpenMeetings, veuillez <a target=\"_blank\" href=\"http://openmeetings.apache.org/\">en installer un</a> avant de poursuivre, ou demander un devis à l'un des fournisseurs officiels de Chamilo. OpenMeetings est un outil de logiciel libre (et gratuit), mais son installation pourrait présenter une certaine complexité et demander des compétences qui ne sont peut-être pas à la portée de tous. Vous pouvez l'installer vous-même à partir de la documentation (disponible publiquement) de OpenMeetings, ou recherchez un soutien professionnel. Ce soutien pourrait générer certains coûts (au moins le temps de la personne qui vous assiste dans l'opération). Dans le plus pur esprit du logiciel libre, nous vous fournissons les outils pour simplifier votre travail dans la mesure de nos possibilités, et nous vous recommandons des professionnels (les fournisseurs officiels de Chamilo) pour vous venir en aide au cas où ceux-ci seraient insuffisants.<br />";
+
+$strings['openmeetings_welcome_message'] = 'Message de bienvenue de OpenMeetings';
+$strings['openmeetings_record_and_store'] = 'Enregistrer les sessions de vidéoconférence';
+
+$strings['plugin_tool_openmeetings'] = 'Vidéo';
+
+$strings['ThereAreNotRecordingsForTheMeetings'] = 'Aucun enregistrement disponible';
+$strings['NoRecording'] = "Pas d'enregistrement";
+

+ 53 - 0
plugin/openmeetings/lang/spanish.php

@@ -0,0 +1,53 @@
+<?php /* License: see /license.txt */
+//Needed in order to show the plugin title
+$strings['plugin_title']        = "OpenMeetings";
+$strings['plugin_comment']      = "Añade una sala de videoconferencia en los cursos de Chamilo con OpenMeetings (om)";
+
+$strings['Videoconference']     = "VideoconferenciaOM";
+$strings['MeetingOpened']       = "Sala abierta";
+$strings['MeetingClosed']       = "Sala cerrada";
+$strings['MeetingClosedComment'] = "Si ha pedido grabar la sesión de videoconferencia en los parámetros del curso, esta grabación aparecerá en la lista siguiente una vez generada.";
+$strings['CloseMeeting']        = "Cerrar sala";
+
+$strings['MeetingDeleted']        = "Eliminar sala";
+$strings['MeetingDeletedComment'] = "";
+
+$strings['VideoConferenceXCourseX']             = "Videoconferencia #%s, curso %s";
+$strings['VideoConferenceAddedToTheCalendar']   = "Videoconferencia añadida al calendario";
+$strings['VideoConferenceAddedToTheLinkTool']   = "Videoconferencia añadida como enlace. Puede editar y publicar el enlace en la página principal del curso desde la herramienta de enlace.";
+
+$strings['GoToTheVideoConference']   = "Ir a la videoconferencia";
+
+$strings['Records']             = "Grabación";
+$strings['Meeting']             = "Sala de conferencia";
+
+$strings['ViewRecord']          = "Ver grabación";
+$strings['CopyToLinkTool']      = "Añadir como enlace del curso";
+
+$strings['EnterConference']     = "Entrar a la videoconferencia";
+$strings['RecordList']          = "Lista de grabaciones";
+$strings['ServerIsNotRunning']  = "El servidor de videoconferencia no está funcionando";
+$strings['ServerIsNotConfigured']  = "El servidor de videoconferencia no está configurado correctamente";
+
+$strings['XUsersOnLine']        = "%s usuario(s) en la sala";
+
+$strings['host'] = 'Host de OpenMeetings';
+$strings['host_help'] = 'Este es el nombre del servidor donde su servidor OpenMeetings está corriendo. Puede ser http://localhost:5080/openmeetings, una dirección IP (ej: http://192.168.13.54:5080/openmeetings) o un nombre de dominio (ej: http://mi.video.com:5080/openmeetings).';
+
+$strings['user'] = 'Usuario';
+$strings['user_help'] = 'Ingrese el usuario con el cual de conectará al servidor OpenMeetings';
+
+$strings['pass'] = 'Clave OpenMeetings';
+$strings['pass_help'] = 'Esta es la llave de seguridad de su servidor OpenMeetings (llamada "salt" en inglés), que permitirá a su servidor de autentifica la instalación de Chamilo (como autorizada). Refiérese a la documentación de OpenMeetings para ubicarla.';
+
+$strings['tool_enable'] = 'Herramienta de videoconferencia OpenMeetings activada';
+$strings['tool_enable_help'] = 'Escoja si desea activar la herramienta de videoconferencia OpenMeetings. Una vez activada, se mostrará como una herramienta adicional en todas las páginas principales de cursos, y los profesores podrán iniciar una conferencia en cualquier momento. Los estudiantes no podrían lanzar una conferencia, solo juntarse a una existente. Si no tiene un servidor de videoconferencia OpenMeetings, por favor <a target=\"_blank\" href=\"http://openmeetings.apache.org/\">configure uno</a> antes de seguir, o pida una cotización a uno de los proveedores oficiales de Chamilo. OpenMeetings es una herramienta de software libre (y gratuita), pero su instalación requiere de competencias que quizás no sean inmediatamente disponibles para todos. Puede instalarla usted mismo o buscar ayuda profesional. Esta ayuda podría no obstante generar algunos costos (por lo menos el tiempo de la persona quien lo ayude). En el puro espíritu del software libre, le ofrecemos las herramientas para hacer su trabajo más simple, en la medida de nuestras posibilidades, y le recomendamos profesionales (los proveedores oficiales de Chamilo) para ayudarlo en caso esto fuera demasiado complicado.<br />';
+
+$strings['openmeetings_welcome_message'] = 'Mensaje de bienvenida de ';
+$strings['openmeetings_record_and_store'] = 'Grabar las sesiones de videoconferencia';
+
+$strings['plugin_tool_openmeetings'] = 'Video';
+
+$strings['ThereAreNotRecordingsForTheMeetings'] = 'No hay grabaciones de sesiones de videoconferencia';
+$strings['NoRecording'] = 'No hay grabación';
+

+ 631 - 0
plugin/openmeetings/lib/openmeetings.class.php

@@ -0,0 +1,631 @@
+<?php
+/**
+ * Chamilo-OpenMeetings integration plugin library, defining methods to connect
+ * to OpenMeetings from Chamilo by calling its web services
+ * @package chamilo.plugin.openmeetings
+ */
+/**
+ * Initialization
+ */
+namespace Chamilo\Plugin\OpenMeetings;
+
+include_once __DIR__.'/session.class.php';
+include_once __DIR__.'/room.class.php';
+include_once __DIR__.'/user.class.php';
+
+/**
+ * Open Meetings-Chamilo connector class
+ */
+class OpenMeetings
+{
+    public $url;
+    public $user;
+    public $pass;
+    public $api;
+    public $user_complete_name = null;
+    public $protocol = 'http://';
+    public $debug = false;
+    public $logout_url = null;
+    public $plugin_enabled = false;
+    public $sessionId = "";
+    public $roomName = '';
+    public $chamiloCourseId;
+    public $chamiloSessionId;
+    public $externalType;
+
+    /**
+     * Constructor (generates a connection to the API and the Chamilo settings
+     * required for the connection to the video conference server)
+     */
+    public function __construct()
+    {
+        global $_configuration;
+
+        // initialize video server settings from global settings
+        $plugin = \OpenMeetingsPlugin::create();
+
+        $om_plugin = $plugin->get('tool_enable');
+        $om_host   = $plugin->get('host');
+        $om_user   = $plugin->get('user');
+        $om_pass   = $plugin->get('pass');
+        $accessUrl = api_get_access_url($_configuration['access_url']);
+        $this->externalType = substr($accessUrl['url'], strpos($accessUrl['url'], '://')+3, -1);
+        if (strcmp($this->externalType, 'localhost') == 0) {
+            $this->externalType = substr(api_get_path(WEB_PATH), strpos(api_get_path(WEB_PATH), '://')+3, -1);
+        }
+        $this->externalType = 'chamilolms.'.$this->externalType;
+        $this->table = \Database::get_main_table('plugin_openmeetings');
+
+        if ($om_plugin) {
+            $user_info = api_get_user_info();
+            $this->user_complete_name = $user_info['complete_name'];
+            $this->user = $om_user;
+            $this->pass = $om_pass;
+            $this->url = $om_host;
+
+            // Setting OM api
+            define('CONFIG_OPENMEETINGS_USER', $this->user);
+            define('CONFIG_OPENMEETINGS_PASS', $this->pass);
+            define('CONFIG_OPENMEETINGS_SERVER_URL', $this->url);
+
+            $this->gateway = new \OpenMeetingsGateway($this->url, $this->user, $this->pass);
+            $this->plugin_enabled = $om_plugin;
+            // The room has a name composed of C + course ID + '-' + session ID
+            $this->chamiloCourseId = api_get_course_int_id();
+            $this->chamiloSessionId = api_get_session_id();
+            $this->roomName = 'C'.$this->chamiloCourseId.'-'.$this->chamiloSessionId;
+            $return = $this->gateway->loginUser();
+            if ($return == 0) {
+                $msg = 'Could not initiate session with server through OpenMeetingsGateway::loginUser()';
+                error_log(__FILE__.'+'.__LINE__.': '.$msg);
+                die($msg);
+            }
+            $this->sessionId = $this->gateway->sessionId;
+        }
+    }
+
+    /**
+     * Checks whether a user is teacher in the current course
+     * @return bool True if the user can be considered a teacher in this course, false otherwise
+     */
+    public function isTeacher()
+    {
+        return api_is_course_admin() || api_is_coach() || api_is_platform_admin();
+    }
+
+    /**
+     * Login the user with OM Server. This generates a session ID that is
+     * specific to the current user, but that does not require specific user data
+     *
+     * It is similar to opening a PHP session. In fact, the session ID is kept
+     * inside the $_SESSION['openmeetings_session'] session variable
+     * @return bool True if the user is correct and false when is incorrect
+     * @deprecated loginUser now called at object instanciation
+     */
+    /**
+    function loginUser()
+    {
+        try {
+            //Verifying if there is already an active session
+            if (empty($_SESSION['openmeetings_session'])) {
+                // Login user returns either 0 or >0, depending on the results
+                // Technically, as long as the SOAP user has been configured in OpenMeetings and OpenMeetings is on, this should always succeed.
+                if ($this->gateway->loginUser()) {
+                    $this->sessionId = $_SESSION['openmeetings_session'] = $this->gateway->session_id;
+                    return true;
+                } else {
+                    error_log('loginUser did not succeed');
+                    return false;
+                }
+            } else {
+                $this->sessionId = $_SESSION['openmeetings_session'];
+                return true;
+            }
+        } catch (SoapFault $e) {
+            error_log(__FILE__.'+'.__LINE__.' Warning: We have detected some problems. Fault: '.$e->faultstring);
+            return false;
+        }
+    }
+    */
+
+    /*
+     * Creating a Room for the meeting
+    * @return bool True if the user is correct and false when is incorrect
+    */
+    public function createMeeting($params)
+    {
+        global $_configuration;
+        // First, try to see if there is an active room for this course and session.
+        $roomId = null;
+
+        $meetingData = \Database::select(
+            '*',
+            $this->table,
+            array(
+                'where' =>
+                array(
+                    'c_id = ?' => $this->chamiloCourseId,
+                    ' AND session_id = ? ' => $this->chamiloSessionId,
+                    ' AND status <> ? ' => 2,
+
+                )
+            ),
+            'first'
+        );
+
+        if ($meetingData != false && count($meetingData) > 0) {
+            //error_log(print_r($meetingData,1));
+            //error_log('Found previous room reference - reusing');
+            // There has been a room in the past for this course. It should
+            // still be on the server, so update (instead of creating a new one)
+            // This fills the following attributes: status, name, comment, chamiloCourseId, chamiloSessionId
+            $room = new Room();
+            $room->loadRoomId($meetingData['room_id']);
+            $roomArray = (array)$room;
+            $roomArray['SID'] = $this->sessionId;
+            $roomId = $this->gateway->updateRoomWithModeration($room);
+            if ($roomId != $meetingData['room_id']) {
+                $msg = 'Something went wrong: the updated room ID ('.$roomId.') is not the same as the one we had ('.$meetingData['room_id'].')';
+                error_log($msg);
+                die($msg);
+            }
+
+        } else {
+            //error_log('Found no previous room - creating');
+            $room = new Room();
+            $room->SID = $this->sessionId;
+            $room->name = $this->roomName;
+            //$room->roomtypes_id = $room->roomtypes_id;
+            $room->comment = urlencode(get_lang('Course').': ' . $params['meeting_name'] . ' - '.$_configuration['software_name']);
+            //$room->numberOfPartizipants = $room->numberOfPartizipants;
+            $room->ispublic = $room->getString('isPublic', 'false');
+            //$room->appointment = $room->getString('appointment');
+            //$room->isDemoRoom = $room->getString('isDemoRoom');
+            //$room->demoTime = $room->demoTime;
+            //$room->isModeratedRoom = $room->getString('isModeratedRoom');
+            $roomId = $this->gateway->createRoomWithModAndType($room);
+        }
+
+        if (!empty($roomId)) {
+            /*
+            // Find the biggest room_id so far, and create a new one
+            if (empty($roomId)) {
+                $roomData = \Database::select('MAX(room_id) as room_id', $this->table, array(), 'first');
+                $roomId = $roomData['room_id'] + 1;
+            }*/
+
+            $params['status'] = '1';
+            $params['meeting_name'] = $room->name;
+            $params['created_at'] = api_get_utc_datetime();
+            $params['room_id'] = $roomId;
+            $params['c_id'] = api_get_course_int_id();
+            $params['session_id'] = api_get_session_id();
+            $params['record'] = ($room->allowRecording?1:0);
+
+            $id = \Database::insert($this->table, $params);
+
+            $this->joinMeeting($id);
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * Returns a meeting "join" URL
+     * @param string The name of the meeting (usually the course code)
+     * @return mixed The URL to join the meeting, or false on error
+     * @todo implement moderator pass
+     * @assert ('') === false
+     * @assert ('abcdefghijklmnopqrstuvwxyzabcdefghijklmno') === false
+     */
+    public function joinMeeting($meetingId)
+    {
+        if (empty($meetingId)) {
+            return false;
+        }
+        $meetingData = \Database::select(
+            '*',
+            $this->table,
+            array('where' => array('id = ? AND status = 1 ' => $meetingId)),
+            'first'
+        );
+
+        if (empty($meetingData)) {
+            if ($this->debug) {
+                error_log("meeting does not exist: $meetingId ");
+            }
+            return false;
+        }
+        $params = array('room_id' => $meetingData['room_id']);
+        $returnVal = $this->setUserObjectAndGenerateRoomHashByURLAndRecFlag($params);
+        $iframe = $this->url . "/?" ."secureHash=" . $returnVal;
+        printf("<iframe src='%s' width='%s' height = '%s' />", $iframe, "100%", 640);
+    }
+
+    /**
+     * Checks if the videoconference server is running.
+     * Function currently disabled (always returns 1)
+     * @return bool True if server is running, false otherwise
+     * @assert () === false
+     */
+    public function isServerRunning()
+    {
+        // Always return true for now as this requires the openmeetings object
+        // to have been instanciated and this includes a loginUser() which
+        // connects to the server
+        return true;
+    }
+
+     /**
+     * Gets the password for a specific meeting for the current user
+     * @return string A moderator password if user is teacher, or the course code otherwise
+     */
+    public function getMeetingUserPassword()
+    {
+        if ($this->isTeacher()) {
+            return $this->getMeetingModerationPassword();
+        } else {
+            return api_get_course_id();
+        }
+    }
+
+    /**
+     * Generated a moderator password for the meeting
+     * @return string A password for the moderation of the video conference
+     */
+    public function getMeetingModerationPassword()
+    {
+        return api_get_course_id().'mod';
+    }
+
+    /**
+     * Get information about the given meeting
+     * @param array ...?
+     * @return mixed Array of information on success, false on error
+     * @assert (array()) === false
+     */
+    public function getMeetingInfo($params)
+    {
+        try {
+            $result = $this->api->getMeetingInfoArray($params);
+            if ($result == null) {
+                if ($this->debug) {
+                    error_log(__FILE__.'+'.__LINE__." Failed to get any response. Maybe we can't contact the OpenMeetings server.");
+                }
+            } else {
+                return $result;
+            }
+        } catch (Exception $e) {
+            if ($this->debug) {
+                error_log(__FILE__.'+'.__LINE__.' Caught exception: ', $e->getMessage(), "\n");
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @param array $params Array of parameters
+     * @return mixed
+     */
+    public function setUserObjectAndGenerateRecordingHashByURL($params)
+    {
+        $username = $_SESSION['_user']['username'];
+        $firstname = $_SESSION['_user']['firstname'];
+        $lastname = $_SESSION['_user']['lastname'];
+        $userId = $_SESSION['_user']['user_id'];
+        $systemType = 'chamilo';
+        $room_id = $params['room_id'];
+
+        $urlWsdl = $this->url."/services/UserService?wsdl";
+        $omServices = new \SoapClient($urlWsdl);
+        $objRec = new User();
+
+        $objRec->SID = $this->sessionId;
+        $objRec->username = $username;
+        $objRec->firstname = $firstname;
+        $objRec->lastname = $lastname;
+        $objRec->externalUserId = $userId;
+        $objRec->externalUserType = $systemType;
+        $objRec->recording_id = $recording_id;
+        $orFn = $omServices->setUserObjectAndGenerateRecordingHashByURL($objRec);
+
+        return $orFn->return;
+    }
+
+    /**
+     * @param Array $params Array of parameters
+     * @return mixed
+     */
+    public function setUserObjectAndGenerateRoomHashByURLAndRecFlag($params)
+    {
+        $username = $_SESSION['_user']['username'];
+        $firstname = $_SESSION['_user']['firstname'];
+        $lastname = $_SESSION['_user']['lastname'];
+        $profilePictureUrl = $_SESSION['_user']['avatar'];
+        $email = $_SESSION['_user']['mail'];
+        $userId = $_SESSION['_user']['user_id'];
+        $systemType = 'Chamilo';
+        $room_id = $params['room_id'];
+        $becomeModerator = ( $this->isTeacher() ? 1 : 0 );
+        $allowRecording = 1; //Provisional
+
+        $urlWsdl = $this->url."/services/UserService?wsdl";
+        $omServices = new \SoapClient($urlWsdl);
+        $objRec = new User();
+
+        $objRec->SID = $this->sessionId;
+        $objRec->username = $username;
+        $objRec->firstname = $firstname;
+        $objRec->lastname = $lastname;
+        $objRec->profilePictureUrl = $profilePictureUrl;
+        $objRec->email = $email;
+        $objRec->externalUserId = $userId;
+        $objRec->externalUserType = $systemType;
+        $objRec->room_id = $room_id;
+        $objRec->becomeModeratorAsInt = $becomeModerator;
+        $objRec->showAudioVideoTestAsInt = 1;
+        $objRec->allowRecording = $allowRecording;
+        $rcFn = $omServices->setUserObjectAndGenerateRoomHashByURLAndRecFlag($objRec);
+
+        return $rcFn->return;
+    }
+
+    /**
+     * Gets all the course meetings saved in the plugin_openmeetings table
+     * @return array Array of current open meeting rooms
+     */
+    public function getCourseMeetings()
+    {
+        $newMeetingsList = array();
+        $item = array();
+        $meetingsList = \Database::select(
+            '*',
+            $this->table,
+            array('where' =>
+                array(
+                    'c_id = ? ' => api_get_course_int_id(),
+                    ' AND session_id = ? ' => api_get_session_id(),
+                    ' AND status <> ? ' => 2 // status deleted
+                )
+            )
+        );
+        /*$urlWsdl = $this->url."/services/RoomService?wsdl";
+        $omServices = new \SoapClient($urlWsdl);*/
+        $room = new Room();
+
+        /*
+        try {
+            $rooms = $this->gateway->getRoomsWithCurrentUsersByType();
+            //$rooms = $omServices->getRoomsPublic(array(
+                //'SID' => $this->sessionId,
+                //'start' => 0,
+                //'max' => 10,
+                //'orderby' => 'name',
+                //'asc' => 'true',
+                //'externalRoomType' => 'chamilo',
+                //'roomtypes_id' => 'chamilo',
+                //)
+            //);
+        } catch (SoapFault $e) {
+            error_log(__FILE__.'+'.__LINE__.' '.$e->faultstring);
+            //error_log($rooms->getDebug());
+            return false;
+        }
+        */
+        $room->SID = $this->sessionId;
+        //error_log(__FILE__.'+'.__LINE__.' Meetings found: '.print_r($room->SID,1));
+        if (!empty($meetingsList)) {
+            foreach ($meetingsList as $meetingDb) {
+                //$room->rooms_id = $meetingDb['room_id'];
+                error_log(__FILE__.'+'.__LINE__.' Meetings found: '.print_r($meetingDb, 1));
+                $remoteMeeting = array();
+                $meetingDb['created_at'] = api_get_local_time($meetingDb['created_at']);
+                $meetingDb['closed_at'] = (!empty($meetingDb['closed_at']) ? api_get_local_time($meetingDb['closed_at']):'');
+                // Fixed value for now
+                $meetingDb['participantCount'] = 40;
+                $rec = $this->gateway->getFlvRecordingByRoomId($meetingDb['room_id']);
+                $links = array();
+                // Links to videos look like these:
+                // http://video2.openmeetings.com:5080/openmeetings/DownloadHandler?fileName=flvRecording_4.avi&moduleName=lzRecorderApp&parentPath=&room_id=&sid=dfc0cac396d384f59242aa66e5a9bbdd
+                $link = $this->url.'/DownloadHandler?fileName=%s&moduleName=lzRecorderApp&parentPath=&room_id=%s&sid=%s';
+                if (!empty($rec)) {
+                    $link1 = sprintf($link, $rec['fileHash'], $meetingDb['room_id'], $this->sessionId);
+                    $link2 = sprintf($link, $rec['alternateDownload'], $meetingDb['room_id'], $this->sessionId);
+                    $links[] = $rec['fileName'].' '.
+                        \Display::url('[.flv]', $link1, array('target' => '_blank')).' '.
+                        \Display::url('[.avi]', $link2, array('target' => '_blank'));
+
+                }
+                $item['show_links']  = implode('<br />', $links);
+
+                // The following code is currently commented because the web service
+                // says this is not allowed by the SOAP user.
+                /*
+                try {
+                    // Get the conference room object from OpenMeetings server - requires SID and rooms_id to be defined
+                    $objRoomId = $this->gateway->getRoomById($meetingDb['room_id']);
+                    if (empty($objRoomId->return)) {
+                        error_log(__FILE__.'+'.__LINE__.' Emptyyyyy ');
+                        //\Database::delete($this->table, "id = {$meetingDb['id']}");
+                        // Don't delete expired rooms, just mark as closed
+                        \Database::update($this->table, array('status' => 0, 'closed_at' => api_get_utc_datetime()), array('id = ? ' => $meetingDb['id']));
+                        continue;
+                    }
+                    //$objCurUs = $omServices->getRoomWithCurrentUsersById($objCurrentUsers);
+                } catch  (SoapFault $e) {
+                    error_log(__FILE__.'+'.__LINE__.' '.$e->faultstring);
+                    exit;
+                }
+                //if( empty($objCurUs->returnMeetingID) ) continue;
+
+                $current_room = array(
+                    'roomtype' => $objRoomId->return->roomtype->roomtypes_id,
+                    'meetingName' => $objRoomId->return->name,
+                    'meetingId' => $objRoomId->return->meetingID,
+                    'createTime' => $objRoomId->return->rooms_id,
+                    'showMicrophoneStatus' => $objRoomId->return->showMicrophoneStatus,
+                    'attendeePw' => $objRoomId->return->attendeePW,
+                    'moderatorPw' => $objRoomId->return->moderators,
+                    'isClosed' => $objRoomId->return->isClosed,
+                    'allowRecording' => $objRoomId->return->allowRecording,
+                    'startTime' => $objRoomId->return->startTime,
+                    'endTime' => $objRoomId->return->updatetime,
+                    'participantCount' => count($objRoomId->return->currentusers),
+                    'maxUsers' => $objRoomId->return->numberOfPartizipants,
+                    'moderatorCount' => count($objRoomId->return->moderators)
+                );
+                    // Then interate through attendee results and return them as part of the array:
+                if (!empty($objRoomId->return->currentusers)) {
+                        foreach ($objRoomId->return->currentusers as $a)
+                          $current_room[] = array(
+                                    'userId' => $a->username,
+                                    'fullName' => $a->firstname . " " . $a->lastname,
+                                    'isMod' => $a->isMod
+                          );
+                }
+                $remoteMeeting = $current_room;
+                */
+
+                if (empty( $remoteMeeting )) {
+                /*
+                    error_log(__FILE__.'+'.__LINE__.' Empty remote Meeting for now');
+                    if ($meetingDb['status'] == 1 && $this->isTeacher()) {
+                        $this->endMeeting($meetingDb['id']);
+                    }
+                */
+                } else {
+                    $remoteMeeting['add_to_calendar_url'] = api_get_self().'?action=add_to_calendar&id='.$meetingDb['id'].'&start='.api_strtotime($meetingDb['startTime']);
+                }
+                $remoteMeeting['end_url'] = api_get_self().'?action=end&id='.$meetingDb['id'];
+                $remoteMeeting['delete_url'] = api_get_self().'?action=delete&id='.$meetingDb['id'];
+
+                //$record_array = array();
+
+    //            if ($meetingDb['record'] == 1) {
+    //                $recordingParams = array(
+    //                    'meetingId' => $meetingDb['id'],        //-- OPTIONAL - comma separate if multiple ids
+    //                );
+    //
+    //                $records = $this->api->getRecordingsWithXmlResponseArray($recordingParams);
+    //                if (!empty($records)) {
+    //                    $count = 1;
+    //                    if (isset($records['message']) && !empty($records['message'])) {
+    //                        if ($records['messageKey'] == 'noRecordings') {
+    //                            $record_array[] = get_lang('NoRecording');
+    //                        } else {
+    //                            //$record_array[] = $records['message'];
+    //                        }
+    //                    } else {
+    //                        foreach ($records as $record) {
+    //                            if (is_array($record) && isset($record['recordId'])) {
+    //                                $url = Display::url(get_lang('ViewRecord'), $record['playbackFormatUrl'], array('target' => '_blank'));
+    //                                if ($this->is_teacher()) {
+    //                                    $url .= Display::url(Display::return_icon('link.gif',get_lang('CopyToLinkTool')), api_get_self().'?action=copy_record_to_link_tool&id='.$meetingDb['id'].'&record_id='.$record['recordId']);
+    //                                    $url .= Display::url(Display::return_icon('agenda.png',get_lang('AddToCalendar')), api_get_self().'?action=add_to_calendar&id='.$meetingDb['id'].'&start='.api_strtotime($meetingDb['created_at']).'&url='.$record['playbackFormatUrl']);
+    //                                    $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?action=delete_record&id='.$record['recordId']);
+    //                                }
+    //                                //$url .= api_get_self().'?action=publish&id='.$record['recordID'];
+    //                                $count++;
+    //                                $record_array[] = $url;
+    //                            } else {
+    //
+    //                            }
+    //                        }
+    //                    }
+    //                }
+    //                //var_dump($record_array);
+    //                $item['show_links']  = implode('<br />', $record_array);
+    //
+    //            }
+    //
+                 //$item['created_at'] = api_convert_and_format_date($meetingDb['created_at']);
+    //            //created_at
+    //
+    //            $item['publish_url'] = api_get_self().'?action=publish&id='.$meetingDb['id'];
+    //            $item['unpublish_url'] = api_get_self().'?action=unpublish&id='.$meetingDb['id'];
+    //
+                //if ($meetingDb['status'] == 1) {
+    //                $joinParams = array(
+    //                    'meetingId' => $meetingDb['id'],        //-- REQUIRED - A unique id for the meeting
+    //                    'username' => $this->user_complete_name,    //-- REQUIRED - The name that will display for the user in the meeting
+    //                    'password' => $pass,            //-- REQUIRED - The attendee or moderator password, depending on what's passed here
+    //                    'createTime' => '',            //-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
+    //                    'userID' => '',            //    -- OPTIONAL - string
+    //                    'webVoiceConf' => ''    //    -- OPTIONAL - string
+    //                );
+    //                $returnVal = $this->setUserObjectAndGenerateRoomHashByURLAndRecFlag( array('room_id' => $meetingDb['id']) );
+    //                $joinUrl = CONFIG_OPENMEETINGS_SERVER_URL . "?" .
+    //                           "secureHash=" . $returnVal;
+    //
+    //                $item['go_url'] = $joinUrl;
+                //}
+                $item = array_merge($item, $meetingDb, $remoteMeeting);
+                //error_log(__FILE__.'+'.__LINE__.'  Item: '.print_r($item,1));
+                $newMeetingsList[] = $item;
+            } //end foreach $meetingsList
+        }
+
+        return $newMeetingsList;
+    }
+
+    /**
+     * Send a command to the OpenMeetings server to close the meeting
+     * @param int $meetingId
+     * @return int
+     */
+    public function endMeeting($meetingId)
+    {
+        try {
+            $room = new Room($meetingId);
+            $room->SID = $this->sessionId;
+            $room->room_id = intval($meetingId);
+            $room->status = false;
+
+            $urlWsdl = $this->url."/services/RoomService?wsdl";
+            $ws = new \SoapClient($urlWsdl);
+
+            $roomClosed = $ws->closeRoom($room);
+            if ($roomClosed > 0) {
+                \Database::update(
+                    $this->table,
+                    array(
+                        'status' => 0,
+                        'closed_at' => api_get_utc_datetime()
+                    ),
+                    array('id = ? ' => $meetingId)
+                );
+            }
+            //error_log(__FILE__.'+'.__LINE__.' Finished closing');
+        } catch (SoapFault $e) {
+            error_log(__FILE__.'+'.__LINE__.' Warning: We have detected some problems: Fault: '.$e->faultstring);
+            exit;
+            return -1;
+        }
+    }
+
+    /**
+     * @param int $id
+     * @return int
+     */
+    public function deleteMeeting($id)
+    {
+        try {
+            $room = new Room();
+            $room->loadRoomId($id);
+            $this->gateway->deleteRoom($room);
+            \Database::update(
+                $this->table,
+                array(
+                    'status' => 2
+                ),
+                array('id = ? ' => $id)
+            );
+            return $id;
+            //error_log(__FILE__.'+'.__LINE__.' Finished closing');
+        } catch (SoapFault $e) {
+            error_log(__FILE__.'+'.__LINE__.' Warning: We have detected some problems: Fault: '.$e->faultstring);
+            exit;
+            return -1;
+        }
+    }
+}

+ 24 - 0
plugin/openmeetings/lib/openmeetings_api.php

@@ -0,0 +1,24 @@
+<?php
+/**
+ * OpenMeetings API
+ * @package chamilo.plugin.openmeetings
+ */
+/**
+ * Class OpenMeetingsAPI
+ */
+class OpenMeetingsAPI
+{
+    private $_user;
+    private $_pass;
+    private $_serverBaseUrl;
+
+    /**
+     * Constructor
+     */
+    public function __construct()
+    {
+        $this->_user = CONFIG_OPENMEETINGS_USER;
+        $this->_pass = CONFIG_OPENMEETINGS_PASS;
+        $this->_serverBaseUrl  = CONFIG_OPENMEETINGS_SERVER_URL;
+    }
+}

+ 474 - 0
plugin/openmeetings/lib/openmeetings_gateway.php

@@ -0,0 +1,474 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License") +  you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+/**
+ * @package chamilo.plugin.openmeetings
+ */
+/**
+ * Init
+ */
+require_once ('openmeetings_rest_service.php');
+/**
+ * Class OpenMeetingsGateway
+ */
+class OpenMeetingsGateway
+{
+    public $sessionId = "";
+    public $config;
+    private $rest;
+    private $_user;
+    private $_pass;
+    private $_url;
+
+    public function __construct($host, $user, $pass)
+    {
+        $this->_user = urlencode($user);
+        $this->_pass = urlencode($pass);
+        $this->_url = $host;
+        if (substr($this->_url, -1, 1) == '/') {
+            $this->_url = substr($this->_url, 0, -1);
+        }
+        $this->rest = new OpenMeetingsRestService();
+        $err = $this->rest->getError();
+        if ($err) {
+            error_log('Constructor error: ' . $err);
+            error_log('Debug: ' . $this->rest->getDebug());;
+            exit();
+        }
+    }
+
+    /**
+     * @param string $name
+     * @return string
+     */
+    public function getRestUrl($name)
+    {
+        return $this->getUrl() . "/services/" . $name . "/";
+    }
+
+    /**
+     * @return string
+     */
+    public function getUrl()
+    {
+        return $this->_url;
+    }
+
+    /**
+     * @param bool $in
+     * @return string
+     */
+    public function var_to_str($in)
+    {
+        if (is_bool($in)) {
+            return $in ? "true" : "false";
+        } else {
+            return $in;
+        }
+    }
+
+    /**
+     * TODO: Get Error Service and show detailed Error Message
+     */
+    public function loginUser()
+    {
+        $returnValue = 0;
+        $response = $this->rest->call($this->getRestUrl("UserService") . "getSession", "session_id");
+
+        if ($this->rest->getError()) {
+            error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($response, 1));
+        } else {
+            $err = $this->rest->getError();
+            if ($err) {
+                error_log('Error: ' . $err);
+            } else {
+                //error_log('getSession returned '.$response. ' - Storing as sessionId');
+                $this->sessionId = $response;
+
+                $url = $this->getRestUrl("UserService")
+                        . "loginUser?"
+                        . "SID=" . $this->sessionId
+                        . "&username=" . $this->_user
+                        . "&userpass=" . $this->_pass;
+                $result = $this->rest->call($url);
+                if ($this->rest->getError()) {
+                    error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
+                } else {
+                    $err = $this->rest->getError();
+                    if ($err) {
+                        error_log('Error '. $err);
+                    } else {
+                        $returnValue = $result;
+                    }
+                }
+            }
+        }
+
+        if ($returnValue > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @param Room $room
+     * @return array|bool|int|null
+     */
+    public function updateRoomWithModeration($room)
+    {
+        $err = $this->rest->getError();
+        if ($err) {
+            error_log('Constructor error: ' . $err);
+            error_log('Debug: ' . $this->rest->getDebug());
+            exit();
+        }
+
+        $isModeratedRoom = false;
+        if ($room->isModeratedRoom == 1) {
+            $isModeratedRoom = true;
+        }
+
+        $url = $this->getRestUrl($this->getRestUrl("RoomService")
+                . "updateRoomWithModeration?SID=" . $this->sessionId
+                . "&room_id=" . $room->room_id
+                . "&name=" . urlencode($room->name)
+                . "&roomtypes_id=" . $room->roomtypes_id
+                . "&comment=" . $room->comment
+                . "&numberOfPartizipants=" . $room->numberOfPartizipants
+                . "&ispublic=false"
+                . "&appointment=false"
+                . "&isDemoRoom=false"
+                . "&demoTime=0"
+                . "&isModeratedRoom=" . $this->var_to_str($isModeratedRoom));
+        //error_log($url);
+        $result = $this->rest->call($url);
+
+        if ($result->fault) {
+            error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
+        } else {
+            $err = $this->rest->getError();
+            if ($err) {
+                error_log('Error: ' . $err);
+            } else {
+                // echo '<h2>Result</h2><pre>'; print_r($result["return"]); echo '</pre>';
+                //error_log('Room updated successfully '.print_r($result,1));
+                return $result;
+            }
+        }
+        return - 1;
+    }
+
+    /**
+     * @param $username
+     * @param $firstname
+     * @param $lastname
+     * @param $userId
+     * @param $systemType
+     * @param $recording_id
+     * @return array|bool|int|null
+     */
+    public function setUserObjectAndGenerateRecordingHashByURL($username, $firstname, $lastname, $userId, $systemType, $recording_id)
+    {
+        $result = $this->rest->call($this->getRestUrl("UserService")
+                . 'setUserObjectAndGenerateRecordingHashByURL?'
+                . 'SID=' . $this->sessionId
+                . '&username=' . urlencode($username)
+                . '&firstname=' . urlencode($firstname)
+                . '&lastname=' . urlencode($lastname)
+                . '&externalUserId=' . $userId
+                . '&externalUserType=' . urlencode($systemType)
+                . '&recording_id=' . $recording_id, 'return');
+
+        if ($result->fault) {
+            error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result, 1));
+        } else {
+            $err = $this->rest->getError();
+            if ($err) {
+                error_log('Error: '.$err);
+            } else {
+                return $result;
+            }
+        }
+        return - 1;
+    }
+
+    /**
+     * @param $username
+     * @param $firstname
+     * @param $lastname
+     * @param $profilePictureUrl
+     * @param $email
+     * @param $userId
+     * @param $systemType
+     * @param $room_id
+     * @param $becomeModerator
+     * @param $allowRecording
+     * @return array|bool|int|null
+     */
+    public function setUserObjectAndGenerateRoomHashByURLAndRecFlag($username, $firstname, $lastname, $profilePictureUrl, $email, $userId, $systemType, $room_id, $becomeModerator, $allowRecording)
+    {
+        $err = $this->rest->getError();
+        if ($err) {
+            error_log('Constructor error: ' . $err);
+            error_log('Debug: ' . $this->rest->getDebug());;
+            exit();
+        }
+
+        $result = $this->rest->call($this->getRestUrl("UserService")
+                . "setUserObjectAndGenerateRoomHashByURLAndRecFlag?"
+                . "SID=" . $this->sessionId
+                . "&username=" . urlencode($username)
+                . "&firstname=" . urlencode($firstname)
+                . "&lastname=" . urlencode($lastname)
+                . "&profilePictureUrl=" . urlencode($profilePictureUrl)
+                . "&email=" . urlencode($email)
+                . "&externalUserId=" . urlencode($userId)
+                . "&externalUserType=" . urlencode($systemType)
+                . "&room_id=" . urlencode($room_id)
+                . "&becomeModeratorAsInt=" . $becomeModerator
+                . "&showAudioVideoTestAsInt=1"
+                . "&allowRecording=" . $this->var_to_str($allowRecording));
+
+        if ($result->fault) {
+            error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result,1));
+        } else {
+            $err = $this->rest->getError();
+            if ($err) {
+                error_log('Error: '.$err);
+            } else {
+                // echo '<h2>Result</h2><pre>'; print_r($result["return"]); echo '</pre>';
+                return $result;
+            }
+        }
+        return - 1;
+    }
+
+    /**
+     * @param Room $openmeetings
+     * @return array|bool|int|null
+     */
+    public function deleteRoom($openmeetings)
+    {
+        $err = $this->rest->getError();
+        if ($err) {
+            error_log('Constructor error: ' . $err);
+            error_log('Debug: ' . $this->rest->getDebug());
+            exit();
+        }
+        $url = $this->getRestUrl("RoomService")."deleteRoom?SID=".$this->sessionId."&rooms_id=".$openmeetings->room_id;
+        $result = $this->rest->call($url);
+
+        if ($result->fault) {
+            error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result,1));
+        } else {
+            $err = $this->rest->getError();
+            if ($err) {
+                error_log('Error: '.$err);
+            } else {
+                // echo '<h2>Result</h2><pre>'; print_r($result["return"]); echo '</pre>';
+                // return $result["return"];
+                return $result;
+            }
+        }
+        return - 1;
+    }
+
+    /**
+     * Generate a new room hash for entering a conference room
+     */
+    public function setUserObjectAndGenerateRoomHash($username, $firstname, $lastname, $profilePictureUrl, $email, $externalUserId, $externalUserType, $room_id, $becomeModeratorAsInt, $showAudioVideoTestAsInt)
+    {
+        $result = $this->rest->call($this->getRestUrl("UserService")
+                . "setUserObjectAndGenerateRoomHash?"
+                . "SID=" . $this->sessionId
+                . "&username=" . urlencode($username)
+                . "&firstname=" . urlencode($firstname)
+                . "&lastname=" . urlencode($lastname)
+                . "&profilePictureUrl=" . urlencode($profilePictureUrl)
+                . "&email=" . urlencode($email)
+                . "&externalUserId=" . urlencode($externalUserId)
+                . "&externalUserType=" . urlencode($externalUserType)
+                . "&room_id=" . $room_id
+                . "&becomeModeratorAsInt=" . $becomeModeratorAsInt
+                . "&showAudioVideoTestAsInt=" . $showAudioVideoTestAsInt);
+
+        if ($result->getError()) {
+            error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result,1));
+        } else {
+            $err = $this->rest->getError();
+            if ($err) {
+                error_log('Error: '.$err);
+            } else {
+                // echo '<h2>Result</h2><pre>'; print_r($result["return"]); echo '</pre>';
+                return $result;
+            }
+        }
+        return - 1;
+    }
+
+    /**
+     * Create a new conference room
+     * @param   Room The room object
+     * @return  The REST call's result
+     */
+    public function createRoomWithModAndType($room)
+    {
+        $service = 'addRoomWithModerationAndExternalType';
+        if ($room->allowRecording) {
+            $service = 'addRoomWithModerationAndRecordingFlags';
+        } elseif ($room->isAudioOnly) {
+            $service = 'addRoomWithModerationExternalTypeAndAudioType';
+        }
+        $url = $this->getRestUrl("RoomService")
+                . $service.'?'
+                . 'SID=' . $room->SID
+                . '&name=' . $room->name
+                . '&roomtypes_id=' . $room->roomtypes_id
+                . '&comment='. $room->comment
+                . '&numberOfPartizipants=' . $room->numberOfPartizipants
+                . '&ispublic=' . $this->var_to_str($room->ispublic)
+                . '&appointment=' . $this->var_to_str($room->appointment)
+                . '&isDemoRoom=' . $this->var_to_str($room->isDemoRoom)
+                . '&demoTime=' . $room->demoTime
+                . '&isModeratedRoom=' . $this->var_to_str($room->isModeratedRoom)
+                . '&externalRoomType=' . $room->externalRoomType;
+        if ($room->allowRecording) {
+            $url .= '&allowUserQuestions=' . $this->var_to_str($room->allowUserQuestions)
+                 . '&isAudioOnly=' . $this->var_to_str($room->isAudioOnly)
+                 . '&waitForRecording=' . $this->var_to_str($room->waitForRecording)
+                 . '&allowRecording=' . $this->var_to_str($room->allowRecording);
+        } elseif ($room->isAudioOnly) {
+            $url .= '&isAudioOnly=' . $this->var_to_str($room->isAudioOnly);
+        }
+        $result = $this->rest->call($url);
+
+        if ($this->rest->fault) {
+            error_log('Fault (Expect - The request contains an invalid SOAP body) '.print_r($result,1));
+        } else {
+            $err = $this->rest->getError();
+            if ($err) {
+                error_log('Error: '.$err);
+            } else {
+                //error_log('Creation of a new room succeeded: ID '.print_r($result,1));
+                return $result;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Gets the list of open rooms of type "Chamilo"
+     * @param  string  $type The type of external system connecting to OpenMeetings
+     * @return bool
+     */
+    public function getRoomsWithCurrentUsersByType($type = 'chamilolms')
+    {
+        //$this->loginUser();
+        if (empty($this->sessionId)) {
+            return false;
+        }
+
+        $url = $this->getRestUrl("RoomService") . "getRoomsWithCurrentUsersByListAndType?SID=" . $this->sessionId
+            . "&start=1&max=1000&orderby=name&asc=true&externalRoomType=chamilolms";
+        //$url = $this->getRestUrl("RoomService")
+        //    . "getRoomTypes?"
+        //    . "SID=" . $this->sessionId;
+        //$url = $this->getRestUrl('JabberService') . 'getAvailableRooms?SID=' . $this->sessionId;
+        //error_log(__FILE__.'+'.__LINE__.' Calling WS: '.$url);
+        $result = $this->rest->call($url, "return");
+        $rooms = array();
+        foreach ($result as $room) {
+            //error_log(__FILE__.'+'.__LINE__.': one room found on remote: '.print_r($room,1));
+            if ($room['externalRoomType'] == $type && count($room['currentusers']) > 0 ) {
+                $rooms[] = $room;
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * Gets details of a remote room by room ID
+     * @param   int $roomId The ID of the room, as of plugin_openmeetings.room_id
+     * @return  mixed Room object
+     */
+    public function getRoomById($roomId = 0)
+    {
+        //$this->loginUser();
+        if (empty($this->sessionId) or empty($roomId)) {
+            return false;
+        }
+        $roomId = intval($roomId);
+
+        $url = $this->getRestUrl("RoomService")
+            . "getRoomById?"
+            . "SID=" . $this->sessionId
+            . "&rooms_id=".$roomId;
+        //error_log(__FILE__.'+'.__LINE__.' Calling WS: '.$url);
+        $result = $this->rest->call($url, "return");
+        return $result;
+    }
+
+    /**
+     * Get list of available recordings made by this instance
+     */
+    public function getRecordingsByExternalRooms()
+    {
+        $url = $this->getRestUrl("RoomService")
+            . "getFlvRecordingByExternalRoomType?"
+            . "SID=" . $this->sessionId
+            . "&externalRoomType=" . urlencode($this->config["moduleKey"]);
+
+        $result = $this->rest->call($url, "return");
+
+        return $result;
+    }
+
+    /**
+     * Get the recording from the room
+     * @param   int $id Room ID
+     * @return array
+     */
+    public function getFlvRecordingByRoomId($id)
+    {
+        $url = $this->getRestUrl("RoomService")
+            . "getFlvRecordingByRoomId?"
+            . "SID=" . $this->sessionId
+            . "&roomId=" . urlencode($id);
+
+        $result = $this->rest->call($url, "return");
+
+        return $result;
+    }
+
+    /**
+     * Get list of available recordings made by user
+     */
+    public function getRecordingsByExternalUser($id)
+    {
+        $url = $this->getRestUrl("RoomService")
+            . "getFlvRecordingByExternalUserId?"
+            . "SID=" . $this->sessionId
+            . "&externalUserId=" . $id;
+
+        $result = $this->rest->call($url, "return");
+
+        return $result;
+    }
+}

+ 91 - 0
plugin/openmeetings/lib/openmeetings_plugin.class.php

@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * Class OpenMeetingsPlugin
+ */
+class OpenMeetingsPlugin extends Plugin
+{
+    public $is_course_plugin = true;
+
+    //When creating a new course this settings are added to the course
+    public $course_settings = array(array(
+        'name' => 'openmeetings_record_and_store',
+        'type' => 'checkbox'
+    ));
+
+    public static function create()
+    {
+        static $result = null;
+        return $result ? $result : $result = new self();
+    }
+
+    protected function __construct()
+    {
+        parent::__construct('2.0', 'Francis Gonzales', array('tool_enable' => 'boolean', 'host' =>'text', 'user' => 'text', 'pass' => 'text'));
+    }
+
+    public function install()
+    {
+        $table = Database::get_main_table('plugin_openmeetings');
+        // id is the internal unique ID (keeps track of historical sessions
+        // status is 0 for closed, 1 for open (available)
+        // room_id is a reference to the meeting ID on the OpenMeetings server.
+        // Any c_id + session_id occurence gets a unique new meeting ID to avoid issues with the number of rooms, as indicated in https://issues.apache.org/jira/browse/OPENMEETINGS-802#comment-13860340
+        $sql = "CREATE TABLE IF NOT EXISTS $table (
+                id INT unsigned NOT NULL auto_increment PRIMARY KEY,
+                c_id INT unsigned NOT NULL DEFAULT 0,
+                session_id INT unsigned NOT NULL DEFAULT 0,
+                room_id INT unsigned NOT NULL DEFAULT 0,
+                meeting_name VARCHAR(255) NOT NULL DEFAULT '',
+                attendee_pw VARCHAR(255) NOT NULL DEFAULT '',
+                moderator_pw VARCHAR(255) NOT NULL DEFAULT '',
+                record INT NOT NULL DEFAULT 0,
+                status INT NOT NULL DEFAULT 0,
+                created_at DATETIME NOT NULL,
+                closed_at DATETIME,
+                calendar_id INT DEFAULT 0,
+                welcome_msg TEXT NOT NULL DEFAULT '')";
+        Database::query($sql);
+
+        //Installing course settings
+        $this->install_course_fields_in_all_courses();
+    }
+
+    public function uninstall()
+    {
+        $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
+        $t_options = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
+        $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
+
+        //New settings
+
+        $sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_tool_enable'";
+        Database::query($sql);
+        $sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_pass'";
+        Database::query($sql);
+        $sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_user'";
+        Database::query($sql);
+        $sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_host'";
+        Database::query($sql);
+
+        //Old settings deleting just in case
+        $sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_plugin'";
+        Database::query($sql);
+        $sql = "DELETE FROM $t_options WHERE variable  = 'openmeetings_plugin'";
+        Database::query($sql);
+//        $sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_plugin_host'";
+//        Database::query($sql);
+//        $sql = "DELETE FROM $t_settings WHERE variable = 'openmeetings_plugin_salt'";
+//        Database::query($sql);
+
+        //hack to get rid of Database::query warning (please add c_id...)
+        $sql = "DELETE FROM $t_tool WHERE name = 'openmeetings' AND c_id = c_id";
+        Database::query($sql);
+
+        $sql = "DROP TABLE IF EXISTS plugin_openmeetings";
+        Database::query($sql);
+
+        //Deleting course settings
+        $this->uninstall_course_fields_in_all_courses();
+    }
+}

+ 181 - 0
plugin/openmeetings/lib/openmeetings_rest_service.php

@@ -0,0 +1,181 @@
+<?php
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License") +  you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+/**
+ * Created on 03.01.2012 by eugen.schwert@gmail.com
+ * @package chamilo.plugin.openmeetings
+ * @requires CURL
+ */
+/**
+ * Class OpenMeetingsRestService
+ */
+class OpenMeetingsRestService
+{
+    function call($request, $returnAttribute = "return")
+    {
+        // This will allow you to view errors in the browser
+        // Note: set "display_errors" to 0 in production
+        // ini_set('display_errors',1);
+        
+        // Report all PHP errors (notices, errors, warnings, etc.)
+        // error_reporting(E_ALL);
+        
+        // URI used for making REST call. Each Web Service uses a unique URL.
+        // $request
+        
+        // Initialize the session by passing the request as a parameter
+        $session = curl_init ( $request );
+        
+        // Set curl options by passing session and flags
+        // CURLOPT_HEADER allows us to receive the HTTP header
+        curl_setopt ( $session, CURLOPT_HEADER, true );
+        
+        // CURLOPT_RETURNTRANSFER will return the response
+        curl_setopt ( $session, CURLOPT_RETURNTRANSFER, true );
+        
+        // Make the request
+        $response = curl_exec ( $session );
+        
+        // Close the curl session
+        curl_close ( $session );
+        
+        // Confirm that the request was transmitted to the OpenMeetings! Image Search Service
+        if (! $response) {
+            die ( "Request OpenMeetings! OpenMeetings Service failed and no response was returned in ".__CLASS__.'::'.__FUNCTION__.'()' );
+        }
+        
+        // Create an array to store the HTTP response codes
+        $status_code = array ();
+        
+        // Use regular expressions to extract the code from the header
+        preg_match ( '/\d\d\d/', $response, $status_code );
+        $bt = debug_backtrace();
+        $caller = array_shift($bt);
+        $extra = ' (from '.$caller['file'].' at line '.$caller['line'].') ';
+        // Check the HTTP Response code and display message if status code is not 200 (OK)
+        switch ($status_code [0]) {
+            case 200 :
+                // Success
+                break;
+            case 503 :
+                error_log( 'Your call to OpenMeetings Web Services '.$extra.' failed and returned an HTTP status of 503.
+                                 That means: Service unavailable. An internal problem prevented us from returning data to you.' );
+                return false;
+                break;
+            case 403 :
+                error_log( 'Your call to OpenMeetings Web Services '.$extra.' failed and returned an HTTP status of 403.
+                                 That means: Forbidden. You do not have permission to access this resource, or are over your rate limit.' );
+                return false;
+                break;
+            case 400 :
+                // You may want to fall through here and read the specific XML error
+                error_log( 'Your call to OpenMeetings Web Services '.$extra.' failed and returned an HTTP status of 400.
+                                 That means:  Bad request. The parameters passed to the service did not match as expected.   
+                                 The exact error is returned in the XML response.' );
+                return false;
+                break;
+            default :
+                error_log( 'Your call to OpenMeetings Web Services '.$extra.' returned an unexpected HTTP status of: ' . $status_code [0] . " Request " . $request );
+                return false;
+        }
+        
+            // Get the XML from the response, bypassing the header
+        if (!($xml = strstr($response, '<ns'))) {
+            $xml = null;
+        }
+            
+        $dom = new DOMDocument();
+        $dom->loadXML($xml);
+            
+        if ($returnAttribute == "") {
+            //echo "XML".$xml."<br/>";
+            return $this->getArray($dom);
+        } else {
+            $returnNodeList = $dom->getElementsByTagName($returnAttribute);
+            $ret = array();
+            foreach ($returnNodeList as $returnNode) {
+                if ($returnNodeList->length == 1) {
+                    return $this->getArray($returnNode);
+                } else {
+                    $ret[] = $this->getArray($returnNode);
+                }
+            }
+            return $ret;
+        }
+            
+    }
+
+    function getArray($node)
+    {
+        if (is_null($node) || !is_object($node)) {
+            return $node;
+        }
+        $array = false;
+        /*
+            echo("!!!!!!!! NODE " . XML_TEXT_NODE
+                    . " :: name = " . $node->nodeName
+                    . " :: local = " . $node->localName
+                    . " :: childs ? " . $node->hasChildNodes()
+                    . " :: count = " . ($node->hasChildNodes() ? $node->childNodes->length : -1)
+                    . " :: type = " . $node->nodeType
+                    . " :: val = " . $node->nodeValue
+                    . "\n");
+        /*
+        if ($node->hasAttributes()) {
+            foreach ($node->attributes as $attr) {
+                $array[$attr->nodeName] = $attr->nodeValue;
+            }
+        }
+        */
+        if ($node->hasChildNodes()) {
+            foreach ($node->childNodes as $childNode) {
+                if ($childNode->nodeType != XML_TEXT_NODE) {
+                    if ($node->hasAttributes()) {
+                        foreach ($node->attributes as $attr) {
+                            if ($attr->localName == "nil") {
+                                return null;
+                            }
+                        }
+                    }
+                    if ($childNode->childNodes->length == 1) {
+                        $array[$childNode->localName] = $this->getArray($childNode);
+                    } else {
+                        $array[$childNode->localName][] = $this->getArray($childNode);
+                    }
+                } else {
+                    return $childNode->nodeValue;
+                    //echo("!!!!!!!! TEXT " . $childNode->nodeValue . "\n");
+                    //$array[$childNode->localName]
+                }
+            }
+        }
+
+        return $array;
+    }
+
+    function getError()
+    {
+        return false;
+    }
+
+    function fault()
+    {
+        return false;
+    }
+}

+ 115 - 0
plugin/openmeetings/lib/room.class.php

@@ -0,0 +1,115 @@
+<?php
+/**
+ * Definition for the room class
+ * @package chamilo.plugin.videoconference
+ */
+namespace Chamilo\Plugin\OpenMeetings;
+
+/**
+ * Class room
+ */
+class Room
+{
+    public $SID;
+    /**
+     * Defining plural and non-plural because of inconsistency in OpenMeetings
+     */
+    public $rooms_id;
+    public $room_id;
+    /**
+     * Status is false for closed, true for open
+     */
+    public $status = false;
+    public $name;
+    /**
+     * Room types are described here http://openmeetings.apache.org/RoomService.html#addRoomWithModerationAndExternalType
+     * 1 = Conference, 2 = Audience, 3 = Restricted, 4 = Interview
+     * $roomTypeId = ( $this->isTeacher() ) ? 1 : 2 ;
+     */
+    public $roomtypes_id = 1;
+    public $comment;
+    public $numberOfPartizipants = 40;
+    public $ispublic = false;
+    public $appointment = false;
+    public $isDemoRoom = false;
+    public $demoTime = 0;
+    public $isModeratedRoom = true;
+    public $externalRoomType = 'chamilolms';
+    public $allowUserQuestions = false;
+    public $isAudioOnly = false;
+    public $waitForRecording = true;
+    public $allowRecording = true;
+    public $chamiloCourseId;
+    public $chamiloSessionId;
+    private $table;
+
+    public function __construct()
+    {
+        $this->table = \Database::get_main_table('plugin_openmeetings');
+        global $_configuration;
+        $this->name = 'C'.api_get_real_course_id().'-'.api_get_session_id();
+        $accessUrl = api_get_access_url($_configuration['access_url']);
+        $this->externalRoomType = substr($accessUrl['url'], strpos($accessUrl['url'],'://')+3,-1);
+        if (strcmp($this->externalRoomType, 'localhost') == 0) {
+            $this->externalRoomType = substr(api_get_path(WEB_PATH), strpos(api_get_path(WEB_PATH),'://')+3, -1);
+        }
+        $this->externalRoomType = 'chamilolms.'.$this->externalRoomType;
+    }
+
+    /**
+     * Get Room by id
+     * @param int $id
+     */
+    public function getRoom($id)
+    {
+        if (!empty($id)) {
+            $roomData = \Database::select('*', $this->table, array('where' => array('id = ?' => $id)), 'first');
+            if (!empty($roomData)) {
+                $this->rooms_id = $this->room_id = $roomData['room_id'];
+                $this->status = $roomData['status'];
+                $this->name = $roomData['meeting_name'];
+                $this->comment = $roomData['welcome_msg'];
+                $this->allowRecording = $roomData['record'];
+                $this->chamiloCourseId = $roomData['c_id'];
+                $this->chamiloSessionId = $roomData['session_id'];
+            }
+        }
+    }
+
+    /**
+     * Sets the room ID and loads as much info as possible from the local table
+     * @param int $id The room ID (from table.room_id)
+     */
+    public function loadRoomId($id)
+    {
+        if (!empty($id)) {
+            $roomData = \Database::select('*', $this->table, array('where' => array('room_id = ?' => $id)), 'last');
+            if (!empty($roomData)) {
+                $this->rooms_id = $this->room_id = $roomData['room_id'];
+                $this->status = $roomData['status'];
+                $this->name = $roomData['meeting_name'];
+                $this->comment = $roomData['welcome_msg'];
+                $this->allowRecording = $roomData['record'];
+                $this->chamiloCourseId = $roomData['c_id'];
+                $this->chamiloSessionId = $roomData['session_id'];
+            }
+        }
+    }
+
+    /**
+     * Gets a string from a boolean attribute
+     * @param string $attribute Name of the attribute
+     * @param mixed  $voidReturn What to return if the value is not defined
+     * @return string The boolean value expressed as string ('true' or 'false')
+     */
+    public function getString($attribute, $voidReturn = false)
+    {
+        if (empty($attribute)) {
+            return false;
+        }
+        if (!isset($this->$attribute)) {
+            return $voidReturn;
+        }
+        return $this->$attribute?'true':'false';
+    }
+}

+ 16 - 0
plugin/openmeetings/lib/session.class.php

@@ -0,0 +1,16 @@
+<?php
+/**
+ * Definition of OpenMeetings session class
+ * @package chamilo.plugin.openmeetings
+ */
+namespace Chamilo\Plugin\OpenMeetings;
+
+/**
+ * Class session
+ */
+class Session
+{
+    public function __construct()
+    {
+    }
+}

+ 31 - 0
plugin/openmeetings/lib/user.class.php

@@ -0,0 +1,31 @@
+<?php
+/**
+ * Definition of the OpenMeetings user class
+ * @package chamilo.plugin.openmeetings
+ */
+namespace Chamilo\Plugin\OpenMeetings;
+
+/**
+ * Class User
+ */
+class User
+{
+    public $SID;
+    public $username;
+    public $userpass;
+    public $firstname;
+    public $lastname;
+    public $profilePictureUrl;
+    public $email;
+    public $externalUserId;
+    public $externalUserType;
+    public $room_id;
+    public $becomeModeratorAsInt;
+    public $showAudioVideoTestAsInt;
+    public $allowRecording;
+    public $recording_id;
+
+    public function __construct()
+    {
+    }
+}

+ 112 - 0
plugin/openmeetings/listing.php

@@ -0,0 +1,112 @@
+<?php
+/**
+ * This script initiates a videoconference session, calling the BigBlueButton API
+ * @package chamilo.plugin.bigbluebutton
+ */
+/**
+ * Initialization
+ */
+
+$course_plugin = 'openmeetings'; //needed in order to load the plugin lang variables
+require_once dirname(__FILE__).'/config.php';
+$plugin = \OpenMeetingsPlugin::create();
+$tool_name = $plugin->get_lang('Videoconference');
+$tpl = new Template($tool_name);
+
+$om = new Chamilo\Plugin\OpenMeetings\OpenMeetings();
+$action = isset($_GET['action']) ? $_GET['action'] : null;
+$teacher = $om->isTeacher();
+
+api_protect_course_script(true);
+$message = null;
+
+if ($teacher) {
+    switch ($action) {
+        case 'add_to_calendar':
+            $course_info = api_get_course_info();
+            $agenda = new Agenda();
+            $agenda->type = 'course';
+
+            $id = intval($_GET['id']);
+            $title = sprintf(get_lang('VideoConferenceXCourseX'), $id, $course_info['name']);
+            $content = Display::url(get_lang('GoToTheVideoConference'), $_GET['url']);
+
+            $event_id = $agenda->add_event($_REQUEST['start'], null, 'true', null, $title, $content, array('everyone'));
+            if (!empty($event_id)) {
+                $message = Display::return_message(get_lang('VideoConferenceAddedToTheCalendar'), 'success');
+            } else {
+                $message = Display::return_message(get_lang('Error'), 'error');
+            }
+            break;
+        case 'copy_record_to_link_tool':
+            $result = $om->copy_record_to_link_tool($_GET['id'], $_GET['record_id']);
+            if ($result) {
+                $message = Display::return_message(get_lang('VideoConferenceAddedToTheLinkTool'), 'success');
+            } else {
+                $message = Display::return_message(get_lang('Error'), 'error');
+            }
+            break;
+        case 'delete_record':
+            /*$result = $om->delete_record($_GET['id']);
+            if ($result) {
+                $message = Display::return_message(get_lang('Deleted'), 'success');
+            } else {
+                $message = Display::return_message(get_lang('Error'), 'error');
+            }*/
+            break;
+        case 'delete':
+            $om->deleteMeeting($_GET['id']);
+            unset($om);
+            $message = Display::return_message(get_lang('MeetingDeleted').'<br />'.get_lang('MeetingDeletedComment'), 'success', false);
+            header('Location: '.api_get_self());
+            exit;
+            break;
+        case 'end':
+            $om->endMeeting($_GET['id']);
+            $message = Display::return_message(get_lang('MeetingClosed').'<br />'.get_lang('MeetingClosedComment'), 'success', false);
+            break;
+        case 'publish':
+            // Not implemented yet
+            //$result = $om->publish_meeting($_GET['id']);
+            break;
+        case 'unpublish':
+            // Not implemented yet
+            //$result = $om->unpublish_meeting($_GET['id']);
+            break;
+        default:
+            break;
+    }
+}
+
+$meetings = $om->getCourseMeetings();
+$openMeeting = false;
+$users_online = 0;
+
+if (!empty($meetings)) {
+    $meetings = array_reverse($meetings);
+    foreach ($meetings as $meeting) {
+        if ($meeting['status'] == 1) {
+            $openMeeting = true;
+        }
+    }
+    $users_online = $meetings->participantCount;
+}
+
+$status = $om->isServerRunning();
+$show_join_button = false;
+if ($openMeeting || $teacher) {
+    $show_join_button = true;
+}
+
+$tpl->assign('allow_to_edit', $teacher);
+$tpl->assign('meetings', $meetings);
+$conference_url = api_get_path(WEB_PLUGIN_PATH).'openmeetings/start.php?launch=1&'.api_get_cidreq();
+$tpl->assign('conference_url', $conference_url);
+$tpl->assign('users_online', $users_online);
+$tpl->assign('openmeetings_status', $status);
+$tpl->assign('show_join_button', $show_join_button);
+$tpl->assign('message', $message);
+$listing_tpl = 'openmeetings/listing.tpl';
+$content = $tpl->fetch($listing_tpl);
+$tpl->assign('content', $content);
+$tpl->display_one_col_template();

+ 66 - 0
plugin/openmeetings/listing.tpl

@@ -0,0 +1,66 @@
+<div class ="row">
+
+{% if openmeetings_status == true %}
+  {% if show_join_button == true %}
+    <div class ="span12" style="text-align:center">
+        <a href="{{ conference_url }}" target="_blank" class="btn btn-primary btn-large">
+            {{ 'EnterConference'|get_lang }}
+        </a>
+        <!--span id="users_online" class="label label-warning">{{ 'XUsersOnLine'| get_lang | format(users_online) }} </span-->
+    </div>
+  {% endif %}
+
+    <div class ="span12">
+        <div class="page-header">
+            <h2>{{ 'RecordList'|get_lang }}</h2>
+        </div>
+
+        <table class="table">
+            <tr>
+                <th>#</th>
+                <th>{{ 'CreatedAt'|get_lang }}</th>
+                <th>{{ 'Status'|get_lang }}</th>
+                <th>{{ 'Records'|get_lang }}</th>
+
+                {% if allow_to_edit  %}
+                    <th>{{ 'Actions'|get_lang }}</th>
+                {% endif %}
+
+            </tr>
+            {% for meeting in meetings %}
+            <tr>
+                <td>{{ meeting.id }}</td>
+                <td>{{ meeting.created_at }}</td>
+                <td>
+                    {% if meeting.status == 1 %}
+                        <span class="label label-success">{{ 'MeetingOpened'|get_lang }}</span>
+                    {% else %}
+                        <span class="label label-info">{{ 'MeetingClosed'|get_lang }}</span>
+                    {% endif %}
+                </td>
+                <td>
+                    {% if meeting.record == 1 %}
+                        {# Record list #}
+                        {{ meeting.show_links }}
+                    {% endif %}
+                </td>
+
+                {% if allow_to_edit %}
+                    <td>
+                    {% if meeting.status == 1 %}
+                        <a class="btn" href="{{ meeting.end_url }} "> {{ 'CloseMeeting' | get_lang }}</a>
+                    {% endif %}
+                    <a class="btn btn-danger" href="{{ meeting.delete_url }} "> {{ 'DeleteMeeting' | get_lang }}</a>
+                    </td>
+                {% endif %}
+
+            </tr>
+            {% endfor %}
+        </table>
+    </div>
+{% else %}
+    <div class ="span12" style="text-align:center">
+        {{ 'ServerIsNotRunning' | return_message('warning') }}
+    </div>
+{% endif %}
+</div>

+ 4 - 0
plugin/openmeetings/plugin.php

@@ -0,0 +1,4 @@
+<?php
+
+require_once dirname(__FILE__).'/config.php';
+$plugin_info = openmeetingsPlugin::create()->get_info();

+ 16 - 0
plugin/openmeetings/readme.txt

@@ -0,0 +1,16 @@
+This plugin will create a link in existing and new courses for the teachers to
+start a videoconference room with OpenMeetings, as well as the administration
+settings to configure this tool.
+
+More info on OpenMeetings: http://openmeetings.apache.org/
+More info on Chamilo: http://www.chamilo.org
+The tasks related to the development of this plugin:
+* https://support.chamilo.org/issues/5491
+* (private system access) https://task.beeznest.com/issues/7046
+* https://issues.apache.org/jira/browse/OPENMEETINGS-802
+People involved:
+* Financed by the Commission Scolaire des Hautes-Rivières, Québec, Canada (and coordinated/executed by the TICFP team)
+* First draft developed by Francis Gonzales Tello - Independent (at the time)
+* First stable version published by Yannick Warnier - BeezNest/Chamilo team
+* Maxim Solodovnik - OpenMeetings team - many thanks to him!
+* Julio Montoya - Corrections and adding features.

+ 70 - 0
plugin/openmeetings/start.php

@@ -0,0 +1,70 @@
+<?php
+/**
+ * This script initiates a video conference session
+ */
+/**
+ * Initialization
+ */
+$course_plugin = 'openmeetings'; //needed in order to load the plugin lang variables
+require_once dirname(__FILE__).'/config.php';
+$tool_name = get_lang('Videoconference');
+$tpl = new Template($tool_name);
+$om = new \Chamilo\Plugin\OpenMeetings\OpenMeetings();
+
+if ($om->isServerRunning()) {
+
+    if (isset($_GET['launch']) && $_GET['launch'] == 1) {
+
+        $meeting_params = array();
+        $meeting_params['meeting_name'] = 'C'.api_get_course_id().'-'.api_get_session_id();
+        $meetings = $om->getCourseMeetings();
+
+        $selectedMeeting = array();
+        /*
+        // Select the meeting with more participantCount.
+        if (!empty($meetings)) {
+            $max = 0;
+            foreach ($meetings as $meeting) {
+                if ($meeting['participantCount'] > $max) {
+                    $selectedMeeting = $meeting;
+                    $max = $meeting['participantCount'];
+                }
+            }
+        }
+        */
+        // Check for the first meeting available with status = 1
+        // (there should be only one at a time, as createMeeting checks for that first
+        if (!empty($meetings)) {
+            foreach ($meetings as $meeting) {
+                if ($meeting['status'] == 1) {
+                    $selectedMeeting = $meeting;
+                }
+            }
+        }
+
+        if (!empty($selectedMeeting)) {
+            $url = $om->joinMeeting($selectedMeeting['id']);
+            if ($url) {
+                header('location: '.$url);
+                exit;
+            }
+        } else {
+            if ($om->isTeacher()) {
+                $om->createMeeting($meeting_params);
+                exit;
+            } else {
+                $url = 'listing.php';
+                header('location: '.$url);
+                exit;
+            }
+        }
+    } else {
+        $url = 'listing.php';
+        header('location: '.$url);
+        exit;
+    }
+} else {
+    $message = Display::return_message(get_lang('ServerIsNotRunning'), 'warning');
+}
+$tpl->assign('message', $message);
+$tpl->display_one_col_template();

+ 13 - 0
plugin/openmeetings/uninstall.php

@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * This script is included by main/admin/settings.lib.php when unselecting a plugin
+ * and is meant to remove things installed by the install.php script in both
+ * the global database and the courses tables
+ * @package chamilo.plugin.bigbluebutton
+ */
+/**
+ * Queries
+ */
+require_once dirname(__FILE__).'/config.php';
+openmeetingsPlugin::create()->uninstall();

+ 1 - 0
plugin/rss/plugin.php

@@ -9,6 +9,7 @@
  * @author Laurent Opprecht
  */
 
+require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php';
 require_once dirname(__FILE__) . '/lib/rss_plugin.class.php';
 
 $plugin_info = RssPlugin::create()->get_info();

+ 33 - 28
plugin/search_course/lib/register_course_widget.class.php

@@ -1,10 +1,10 @@
 <?php
 
 /**
- * Register course widget.
+ * Register course widget. 
  * Handles user's registration action.
  * Display a register to course form if required.
- *
+ * 
  * @copyright (c) 2011 University of Geneva
  * @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
  * @author Laurent Opprecht
@@ -14,14 +14,14 @@ class RegisterCourseWidget
     const ACTION_SUBSCRIBE = 'subscribe';
 
     const PARAM_SUBSCRIBE = 'subscribe';
-    const PARAM_PASSCODE  = 'course_registration_code';
+    const PARAM_PASSCODE = 'course_registration_code';
 
     /**
      * Returns $_POST data for $key is it exists or $default otherwise.
-     *
+     * 
      * @param string $key
      * @param object $default
-     * @return string
+     * @return string 
      */
     public static function post($key, $default = '')
     {
@@ -30,10 +30,10 @@ class RegisterCourseWidget
 
     /**
      * Returns $_GET data for $key is it exists or $default otherwise.
-     *
+     * 
      * @param string $key
      * @param object $default
-     * @return string
+     * @return string 
      */
     public static function get($key, $default = '')
     {
@@ -56,76 +56,80 @@ class RegisterCourseWidget
 
     /**
      * Handle the subscribe action.
-     *
+     * 
      * @return bool
      */
     function action_subscribe_user()
     {
         $action = self::get('action');
-        if ($action != self::ACTION_SUBSCRIBE) {
+        if ($action != self::ACTION_SUBSCRIBE)
+        {
             return false;
         }
 
         $course_code = self::post(self::PARAM_SUBSCRIBE);
-        if (empty($course_code)) {
+        if (empty($course_code))
+        {
             return false;
         }
-
+        
         $registration_code = self::post(self::PARAM_PASSCODE);
 
-        if ($this->subscribe_user($course_code, $registration_code)) {
+        if ($this->subscribe_user($course_code, $registration_code))
+        {
             Display::display_confirmation_message(get_lang('EnrollToCourseSuccessful'));
-
             return;
         }
-        if (!empty($registration_code)) {
+        if (!empty($registration_code))
+        {
             Display::display_error_message(get_lang('CourseRegistrationCodeIncorrect'));
         }
         $this->display_form($course_code);
-
         return true;
     }
 
     /**
      * Regiser a user to a course.
      * Returns true on success, false otherwise.
-     *
+     * 
      * @param string $course_code
      * @param string $registration_code
      * @param int $user_id
-     * @return bool
+     * @return bool 
      */
     function subscribe_user($course_code, $registration_code = '', $user_id = null)
     {
-        $course                  = $this->retrieve_course($course_code);
+        $course = $this->retrieve_course($course_code);
         $course_regisration_code = $course['registration_code'];
-        if (!empty($course_regisration_code) && $registration_code != $course_regisration_code) {
+        if (!empty($course_regisration_code) && $registration_code != $course_regisration_code)
+        {
             return false;
         }
 
-        if (empty($user_id)) {
+        if (empty($user_id))
+        {
             global $_user;
             $user_id = $_user['user_id'];
         }
 
-        return (bool)CourseManager::add_user_to_course($user_id, $course['real_id']);
+        return (bool) CourseManager::add_user_to_course($user_id, $course_code);
     }
 
     /**
      * Display the course registration form.
      * Asks for registration code/password.
-     *
+     * 
      * @param string $course_code
      */
     function display_form($course_code)
     {
         global $stok;
 
-        $course                         = $this->retrieve_course($course_code);
-        $self                           = $_SERVER['REQUEST_URI'];
-        $course_code                    = $course['code'];
-        $course_visual_code             = $course['visual_code'];
-        $course_title                   = $course['title'];
+        $course = $this->retrieve_course($course_code);
+        $self = $_SERVER['REQUEST_URI'];
+        $course_code = $course['code'];
+        $course_visual_code = $course['visual_code'];
+        $course_title = $course['title'];
         $submit_registration_code_label = get_lang("SubmitRegistrationCode");
         $course_requires_password_label = get_lang('CourseRequiresPassword');
 
@@ -148,10 +152,11 @@ EOT;
     /**
      *
      * @param type $course_code
-     * @return type
+     * @return type 
      */
     function retrieve_course($course_code)
     {
+        require_once api_get_path(SYS_PATH) . '/main/inc/lib/course.lib.php';
         return CourseManager::get_course_information($course_code);
     }
 

+ 30 - 30
plugin/search_course/lib/search_course_widget.class.php

@@ -3,9 +3,9 @@
 require_once dirname(__FILE__) . '/register_course_widget.class.php';
 
 /**
- * Search course widget.
+ * Search course widget. 
  * Display a search form and a list of courses that matches the search.
- *
+ * 
  * @copyright (c) 2011 University of Geneva
  * @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
  * @author Laurent Opprecht
@@ -18,10 +18,10 @@ class SearchCourseWidget
 
     /**
      * Returns $_POST data for $key is it exists or $default otherwise.
-     *
+     * 
      * @param string $key
      * @param object $default
-     * @return string
+     * @return string 
      */
     public static function post($key, $default = '')
     {
@@ -30,10 +30,10 @@ class SearchCourseWidget
 
     /**
      * Returns $_GET data for $key is it exists or $default otherwise.
-     *
+     * 
      * @param string $key
      * @param object $default
-     * @return string
+     * @return string 
      */
     public static function get($key, $default = '')
     {
@@ -91,7 +91,7 @@ class SearchCourseWidget
     }
 
     /**
-     *
+     * 
      */
     function accept()
     {
@@ -100,10 +100,10 @@ class SearchCourseWidget
 
     /**
      * Display the search course widget:
-     *
+     * 
      * Title
      * Search form
-     *
+     * 
      * Search results
      */
     function run()
@@ -216,7 +216,7 @@ EOT;
     /**
      *
      * @param array $courses
-     * @return bool
+     * @return bool 
      */
     function display_list($courses)
     {
@@ -227,8 +227,8 @@ EOT;
 
         $user_courses = $this->retrieve_user_courses();
 
-        $display_coursecode = (api_get_setting('display_coursecode_in_courselist') == 'true');
-        $display_teacher = (api_get_setting('display_teacher_in_courselist') == 'true');
+        $display_coursecode = (get_setting('display_coursecode_in_courselist') == 'true');
+        $display_teacher = (get_setting('display_teacher_in_courselist') == 'true');
 
         echo '<table cellpadding="4">';
         foreach ($courses as $key => $course)
@@ -262,13 +262,13 @@ EOT;
     }
 
     /**
-     * Displays the subscribe icon if subscribing is allowed and
+     * Displays the subscribe icon if subscribing is allowed and 
      * if the user is not yet subscribed to this course
-     *
+     * 
      * @global type $stok
      * @param array $current_course
      * @param array $user_courses
-     * @return bool
+     * @return bool 
      */
     function display_subscribe_icon($current_course, $user_courses)
     {
@@ -289,7 +289,7 @@ EOT;
             return false;
         }
 
-        //Subscribe form
+        //Subscribe form     
         $self = $_SERVER['PHP_SELF'];
         echo <<<EOT
                 <form action="$self?action=subscribe" method="post">
@@ -307,10 +307,10 @@ EOT;
 EOT;
         }
 
-        $web_path = api_get_path(WEB_IMG_PATH);
+        $web_path = api_get_path(WEB_PATH);
         $subscribe_label = get_lang('Subscribe');
         echo <<<EOT
-                    <input type="image" name="unsub" src="$web_path/enroll.gif" alt="$subscribe_label" />$subscribe_label
+                    <input type="image" name="unsub" src="$web_path/main/img/enroll.gif" alt="$subscribe_label" />$subscribe_label
                 </form>
 EOT;
         return true;
@@ -323,9 +323,9 @@ EOT;
     /**
      * Search courses that match the search term.
      * Search is done on the code, title and tutor fields.
-     *
-     * @param string $search_term
-     * @return array
+     * 
+     * @param string $search_term 
+     * @return array 
      */
     function retrieve_courses($search_term)
     {
@@ -348,9 +348,9 @@ EOT;
         }
 
         $sql = <<<EOT
-                SELECT * FROM $course_table
-                WHERE ($course_fiter) AND (code LIKE '%$search_term%' OR visual_code LIKE '%$search_term%' OR title LIKE '%$search_term%' OR tutor_name LIKE '%$search_term%')
-                ORDER BY title, visual_code ASC
+                SELECT * FROM $course_table 
+                WHERE ($course_fiter) AND (code LIKE '%$search_term%' OR visual_code LIKE '%$search_term%' OR title LIKE '%$search_term%' OR tutor_name LIKE '%$search_term%') 
+                ORDER BY title, visual_code ASC      
 EOT;
 
         $result = array();
@@ -374,9 +374,9 @@ EOT;
 
     /**
      * Retrieves courses that the user is subscribed to
-     *
+     * 
      * @param int $user_id
-     * @return array
+     * @return array 
      */
     function retrieve_user_courses($user_id = null)
     {
@@ -393,7 +393,7 @@ EOT;
                                       course.title i, course.tutor_name t, course.db_name db, course.directory dir, course_rel_user.status status,
 				      course_rel_user.sort sort, course_rel_user.user_course_cat user_course_cat
 		               FROM $course_table course, $user_course_table course_rel_user
-		               WHERE course.id = course_rel_user.c_id
+		               WHERE course.code = course_rel_user.course_code
 		                     AND course_rel_user.user_id = $user_id
 		               ORDER BY course_rel_user.sort ASC";
         $result = array();
@@ -418,15 +418,15 @@ EOT;
     }
 
     /*
-     * Utility functions - Utility functions - Utility functions
+     * Utility functions - Utility functions - Utility functions 
      */
 
     /**
      * Removes from $courses all courses the user is subscribed to.
-     *
+     * 
      * @global array $_user
      * @param array $courses
-     * @return array
+     * @return array 
      */
     function filter_out_user_courses($courses)
     {

+ 2 - 1
plugin/search_course/plugin.php

@@ -1,10 +1,11 @@
-<?php
+<?php 
 /**
  * @copyright (c) 2011 University of Geneva
  * @license GNU General Public License - http://www.gnu.org/copyleft/gpl.html
  * @author Laurent Opprecht
  */
 
+require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php';
 require_once dirname(__FILE__) . '/lib/search_course_plugin.class.php';
 
 $plugin_info = SearchCoursePlugin::create()->get_info();

+ 7 - 7
plugin/share_buttons/plugin.php

@@ -1,20 +1,20 @@
 <?php
 /**
  * This script is a configuration file for the add_this plugin.
- * These settings will be used in the administration interface for plugins 
+ * These settings will be used in the administration interface for plugins
  * (Chamilo configuration settings->Plugins)
  * @package chamilo.plugin
  * @author Julio Montoya <gugli100@gmail.com>
  */
 /* Plugin config */
 
-//the plugin title
+// The plugin title.
 $plugin_info['title']       = 'Share this page';
-//the comments that go with the plugin
+// The comments that go with the plugin.
 $plugin_info['comment']     = "Show social icons to share a page using addthis.com";
-//the plugin version
+// The plugin version.
 $plugin_info['version']     = '1.0';
-//the plugin author
+// The plugin author.
 $plugin_info['author']      = 'Julio Montoya';
-//For bigger icons change this value to addthis_32x32_style
-$plugin_info['icon_class']   = ''; 
+// For bigger icons change this value to addthis_32x32_style
+$plugin_info['icon_class']   = '';

+ 2 - 2
plugin/show_regions/index.php

@@ -1,9 +1,9 @@
 <?php
 
-//only show the region information if the admin is logged in
+// Only show the region information if the admin is logged in.
 if (api_is_platform_admin()) {
     echo '<div style="color:black;height:50px;width:200px;background-color:#FFE378">';
     //We can have access to the current block and the block information with the variable $plugin_info (see your plugin.php)
     echo $plugin_info['current_region'];
-    echo '</div>';    
+    echo '</div>';
 }

+ 11 - 12
plugin/show_user_info/index.php

@@ -1,18 +1,17 @@
 <?php
-
-//A user must be logged in
+// A user must be logged in.
 $_template['show_message']   = false;
 
 if (!api_is_anonymous()) {
     $_template['show_message']   = true;
-    
-    //Getting the current user id
-    $user_id = api_get_user_id();    
-    
-    //Getting the current user info
+
+    // Getting the current user id.
+    $user_id = api_get_user_id();
+
+    //Getting the current user info.
     $user_info = api_get_user_info($user_id);
-            
-    //You can also use template setting variables in the special variable called template
-    $_template['user_info']   = $user_info;
-    $_template['username']    = $user_info['username'];
-}
+
+    // You can also use template setting variables in the special variable called template.
+    $_template['user_info'] = $user_info;
+    $_template['username'] = $user_info['username'];
+}

+ 10 - 12
plugin/show_user_info/plugin.php

@@ -9,15 +9,13 @@
  * Plugin details (must be present)
  */
 
-//the plugin title
-$plugin_info['title']      = 'Show user information';
-
-//the comments that go with the plugin
-$plugin_info['comment']     = "Shows a welcome message, (this is an example to uses the template system: Twig)";
-//the plugin version
-$plugin_info['version']     = '1.0';
-//the plugin author
-$plugin_info['author']      = 'Julio Montoya';
-
-//set the smarty templates that are going to be used
-$plugin_info['templates']   = array('template.tpl');
+// The plugin title
+$plugin_info['title'] = 'Show user information';
+// The comments that go with the plugin
+$plugin_info['comment'] = "Shows a welcome message, (this is an example to uses the template system: Twig)";
+// The plugin version
+$plugin_info['version'] = '1.0';
+// The plugin author
+$plugin_info['author'] = 'Julio Montoya';
+// Set the templates that are going to be used
+$plugin_info['templates'] = array('template.tpl');

+ 0 - 2
plugin/static/index.php

@@ -1,9 +1,7 @@
 <?php
 
 $plugin = StaticPlugin::create();
-
 $content = $plugin->get_content();
-
 $title = $plugin->get_block_title();
 $title = $title ? "<h4>$title</h4>" : '';
 

+ 2 - 3
plugin/static/lib/static_plugin.class.php

@@ -9,10 +9,9 @@
  */
 class StaticPlugin extends Plugin
 {
-
     /**
      *
-     * @return StaticPlugin 
+     * @return StaticPlugin
      */
     static function create()
     {
@@ -35,4 +34,4 @@ class StaticPlugin extends Plugin
         parent::__construct('1.1', 'Laurent Opprecht', array('block_title' => 'text', 'content' => 'wysiwyg'));
     }
 
-}
+}

+ 1 - 0
plugin/static/plugin.php

@@ -6,6 +6,7 @@
  * @author Laurent Opprecht
  */
 
+require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php';
 require_once dirname(__FILE__) . '/lib/static_plugin.class.php';
 
 $plugin_info = StaticPlugin::create()->get_info();

+ 10 - 0
plugin/ticket/config.install.php

@@ -0,0 +1,10 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+/* bbb parameters that will be registered in the course settings */
+
+require_once '../../main/inc/global.inc.php';
+require_once api_get_path(LIBRARY_PATH).'plugin.class.php';
+
+require_once 'lib/ticket.class.php';
+require_once 'lib/ticket_plugin.class.php';

+ 45 - 0
plugin/ticket/config.php

@@ -0,0 +1,45 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+/* Tables names constants */
+define('PLUGIN_NAME', 'ticket');
+define('TABLE_SUPPORT_ASSIGNED_LOG', 'tck_assigned_log');
+define('TABLE_SUPPORT_CATEGORY', 'tck_category');
+define('TABLE_SUPPORT_MESSAGE', 'tck_message');
+define('TABLE_SUPPORT_PRIORITY', 'tck_priority');
+define('TABLE_SUPPORT_PROJECT', 'tck_project');
+define('TABLE_SUPPORT_STATUS', 'tck_status');
+define('TABLE_SUPPORT_TICKET', 'tck_ticket');
+define('TABLE_SUPPORT_MESSAGE_ATTACHMENTS', 'tck_message_attachments');
+
+/* Ticket status constants */
+define('NEWTCK', 'NAT'); // New ticket unassigned responsible
+define('PENDING', 'PND'); // User waiting answer
+define('UNCONFIRMED', 'XCF'); // Waiting for user response
+define('CLOSE', 'CLS'); // Close ticket
+define('REENVIADO', 'REE'); // @todo delete option. This is a location of USIL
+
+/* Ticket priority constants */
+define('NORMAL', 'NRM');
+define('HIGH', 'ALT');
+define('LOW', 'LOW');
+
+/* Ticket source constants */
+define('SRC_EMAIL', 'MAI');
+define('SRC_PHONE', 'TEL');
+define('SRC_PRESC', 'PRE');
+
+/* Ticket category constants */
+define('CAT_DOCU', 'DOC');
+define('CAT_FORO', 'FOR');
+define('CAT_ANNU', 'ANN');
+
+require_once __DIR__.'/../../main/inc/global.inc.php';
+require_once api_get_path(LIBRARY_PATH).'plugin.class.php';
+require_once api_get_path(LIBRARY_PATH).'course.lib.php';
+require_once api_get_path(LIBRARY_PATH).'mail.lib.inc.php';
+include_once api_get_path(LIBRARY_PATH).'export.lib.inc.php';
+
+require_once api_get_path(PLUGIN_PATH).PLUGIN_NAME.'/lib/ticket.class.php';
+require_once api_get_path(PLUGIN_PATH).PLUGIN_NAME.'/lib/ticket_plugin.class.php';
+require_once api_get_path(PLUGIN_PATH).PLUGIN_NAME.'/s/ticket.class.php';

+ 137 - 0
plugin/ticket/database.php

@@ -0,0 +1,137 @@
+<?php
+/**
+ * Contains the SQL for the tickets management plugin database structure
+ */
+$table = Database::get_main_table(TABLE_SUPPORT_ASSIGNED_LOG);
+$sql = "CREATE TABLE IF NOT EXISTS ".$table." (
+        iid int unsigned not null,
+        ticket_id int UNSIGNED DEFAULT NULL,
+        user_id int UNSIGNED DEFAULT NULL,
+        assigned_date datetime DEFAULT NULL,
+        sys_insert_user_id int UNSIGNED DEFAULT NULL,
+        PRIMARY KEY PK_ticket_assigned_log (iid),
+        KEY FK_ticket_assigned_log (ticket_id))";
+Database::query($sql);
+
+$table = Database::get_main_table(TABLE_SUPPORT_CATEGORY);
+$sql = "CREATE TABLE IF NOT EXISTS ".$table." (
+        iid int unsigned not null,
+        category_id char(3) NOT NULL,
+        project_id char(3) NOT NULL,
+        name varchar(100) NOT NULL,
+        description varchar(255) NOT NULL,
+        total_tickets int UNSIGNED NOT NULL DEFAULT '0',
+        course_required char(1) NOT NULL,
+        sys_insert_user_id int UNSIGNED DEFAULT NULL,
+        sys_insert_datetime datetime DEFAULT NULL,
+        sys_lastedit_user_id int UNSIGNED DEFAULT NULL,
+        sys_lastedit_datetime datetime DEFAULT NULL,
+        PRIMARY KEY (iid))";
+Database::query($sql);
+
+$table = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+$sql = "CREATE TABLE IF NOT EXISTS ".$table." (
+        message_id int UNSIGNED NOT NULL,
+        ticket_id int UNSIGNED NOT NULL,
+        subject varchar(150) DEFAULT NULL,
+        message text NOT NULL,
+        status char(3) NOT NULL,
+        ip_address varchar(16) DEFAULT NULL,
+        sys_insert_user_id int UNSIGNED DEFAULT NULL,
+        sys_insert_datetime datetime DEFAULT NULL,
+        sys_lastedit_user_id int UNSIGNED DEFAULT NULL,
+        sys_lastedit_datetime datetime DEFAULT NULL,
+        PRIMARY KEY (message_id),
+        KEY FK_tick_message (ticket_id) )";
+Database::query($sql);
+
+$table = Database::get_main_table(TABLE_SUPPORT_MESSAGE_ATTACHMENTS);
+$sql = "CREATE TABLE IF NOT EXISTS ".$table." (
+        iid int unsigned not null,
+        message_attch_id char(2) NOT NULL,
+        message_id char(2) NOT NULL,
+        ticket_id int UNSIGNED NOT NULL,
+        path varchar(255) NOT NULL,
+        filename varchar(255) NOT NULL,
+        size varchar(25) DEFAULT NULL,
+        sys_insert_user_id int UNSIGNED DEFAULT NULL,
+        sys_insert_datetime datetime DEFAULT NULL,
+        sys_lastedit_user_id int UNSIGNED DEFAULT NULL,
+        sys_lastedit_datetime datetime DEFAULT NULL,
+        PRIMARY KEY (iid),
+        KEY ticket_message_id_fk (message_id))";
+Database::query($sql);
+
+$table = Database::get_main_table(TABLE_SUPPORT_PRIORITY);
+$sql = "CREATE TABLE IF NOT EXISTS ".$table." (
+        iid int unsigned not null,
+        priority_id char(3) NOT NULL,
+        priority varchar(20) DEFAULT NULL,
+        priority_desc varchar(250) DEFAULT NULL,
+        priority_color varchar(25) DEFAULT NULL,
+        priority_urgency tinyint DEFAULT NULL,
+        sys_insert_user_id int UNSIGNED DEFAULT NULL,
+        sys_insert_datetime datetime DEFAULT NULL,
+        sys_lastedit_user_id int UNSIGNED DEFAULT NULL,
+        sys_lastedit_datetime datetime DEFAULT NULL,
+        PRIMARY KEY (iid))";
+Database::query($sql);
+
+$table = Database::get_main_table(TABLE_SUPPORT_PROJECT);
+$sql = "CREATE TABLE IF NOT EXISTS ".$table." (
+        iid int unsigned not null,
+        project_id char(3) NOT NULL,
+        name varchar(50) DEFAULT NULL,
+        description varchar(250) DEFAULT NULL,
+        email varchar(50) DEFAULT NULL,
+        other_area tinyint NOT NULL DEFAULT '0',
+        sys_insert_user_id int UNSIGNED DEFAULT NULL,
+        sys_insert_datetime datetime DEFAULT NULL,
+        sys_lastedit_user_id int UNSIGNED DEFAULT NULL,
+        sys_lastedit_datetime datetime DEFAULT NULL,
+        PRIMARY KEY (iid))";
+Database::query($sql);
+
+$table = Database::get_main_table(TABLE_SUPPORT_STATUS);
+$sql = "CREATE TABLE IF NOT EXISTS ".$table." (
+        iid int unsigned not null,
+        status_id char(3) NOT NULL,
+        name varchar(100) NOT NULL,
+        description varchar(255) DEFAULT NULL,
+        PRIMARY KEY (iid))";
+Database::query($sql);
+
+$table = Database::get_main_table(TABLE_SUPPORT_TICKET);
+$sql = "CREATE TABLE IF NOT EXISTS ".$table." (
+        ticket_id int UNSIGNED NOT NULL AUTO_INCREMENT,
+        ticket_code char(12) DEFAULT NULL,
+        project_id char(3) DEFAULT NULL,
+        category_id char(3) NOT NULL,
+        priority_id char(3) NOT NULL,
+        course_id int UNSIGNED NOT NULL,
+        request_user int UNSIGNED NOT NULL,
+        personal_email varchar(150) DEFAULT NULL,
+        assigned_last_user int UNSIGNED NOT NULL DEFAULT '0',
+        status_id char(3) NOT NULL,
+        total_messages int UNSIGNED NOT NULL DEFAULT '0',
+        keyword varchar(250) DEFAULT NULL,
+        source char(3) NOT NULL,
+        start_date datetime NOT NULL,
+        end_date datetime DEFAULT NULL,
+        sys_insert_user_id int UNSIGNED DEFAULT NULL,
+        sys_insert_datetime datetime DEFAULT NULL,
+        sys_lastedit_user_id int UNSIGNED DEFAULT NULL,
+        sys_lastedit_datetime datetime DEFAULT NULL,
+        PRIMARY KEY (ticket_id),
+        UNIQUE KEY UN_ticket_code (ticket_code),
+        KEY FK_ticket_priority (priority_id),
+        KEY FK_ticket_category (project_id,category_id))";
+Database::query($sql);
+
+// Menu main tabs
+//$table = Database::get_main_table('ticket_ticket');
+//$sql = "INSERT INTO settings_current
+//(variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable)
+//VALUES
+//('show_tabs', 'tickets', 'checkbox', 'Platform', 'true', 'ShowTabsTitle', 'ShowTabsComment', NULL, 'TabsTickets', 1)";
+//Database::query($sql);

+ 1 - 0
plugin/ticket/index.php

@@ -0,0 +1 @@
+<?php

+ 13 - 0
plugin/ticket/install.php

@@ -0,0 +1,13 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * This script is included by main/admin/settings.lib.php and generally
+ * includes things to execute in the main database (settings_current table)
+ * @package chamilo.plugin.bigbluebutton
+ */
+/**
+ * Initialization
+ */
+
+require_once dirname(__FILE__).'/config.php';
+TicketPlugin::create()->install();

+ 35 - 0
plugin/ticket/lang/english.php

@@ -0,0 +1,35 @@
+<?php /* License: see /license.txt */
+//Needed in order to show the plugin title
+$strings['plugin_title']        = "Tickets";
+$strings['plugin_comment']      = "Plugin to include a support tickets system inside Chamilo.";
+$strings['tool_enable']         = "Enable Ticket plugin";
+$strings['tool_enable_help']    = "Enabling the ticket tool will make a new tab available in the main horizontal menu. This tab will appear for all users and will lead them to the tickets management system where they can check the status of their tickets.";
+
+$strings['TicketNum']     = "Ticket #";
+$strings['Date']          = "Date";
+$strings['DateLastEdition']   = "Last edited";
+$strings['Category']      = "Category";
+$strings['User']          = "User";
+$strings['Program']       = "Program";
+$strings['Responsible']   = "Assigned to";
+$strings['Status']        = "Status";
+$strings['Message']      = "Messages";
+$strings['Description']   = "Description";
+
+$strings['MyTickets']      = "My Tickets";
+$strings['MsgWelcome']     = "Welcome to YOUR tickets section. Here, you'll be able to track the state of all the tickets you created in the main tickets section";
+$strings['TckSuccessSave'] = "Your ticket has been created successfully";
+
+$strings['ValidUser']      = "Please select a user";
+$strings['ValidType']      = "Please select a type";
+$strings['ValidSubject']   = "Please select a topic";
+$strings['ValidCourse']    = "Please select a course";
+$strings['ValidEmail']     = "The e-mail address must be valid";
+$strings['ValidMessage']   = "You must enter a message";
+
+$strings['Presential']     = "Presential";
+$strings['PersonalEmail']  = "Personal e-mail";
+$strings['Optional']       = "Optional";
+$strings['ErrorRegisterMessage'] = "The ticket could not be created";
+$strings['Source']       = "Source";
+

+ 33 - 0
plugin/ticket/lang/french.php

@@ -0,0 +1,33 @@
+<?php /* License: see /license.txt */
+//Needed in order to show the plugin title
+$strings['plugin_title']        = "Tickets";
+$strings['plugin_comment']      = "Plugin de gestion des tickets de support.";
+
+$strings['TicketNum']     = "Ticket #";
+$strings['Date']          = "Date";
+$strings['DateLastEdition']   = "Dernière modification";
+$strings['Category']      = "Catégorie";
+$strings['User']          = "Utilisateur";
+$strings['Program']       = "Programme";
+$strings['Responsible']   = "Assigné à";
+$strings['Status']        = "Statut";
+$strings['Message']      = "Messages";
+$strings['Description']   = "Description";
+
+$strings['MyTickets']      = "Mes tickets";
+$strings['MsgWelcome']     = "Ceci est la section MES Tickets, où vous pouvez suivre l'évolution des tickets que vous avez créé";
+$strings['TckSuccessSave'] = "Votre ticket a été enregistré";
+
+$strings['ValidUser']      = "Veuillez sélectionner un utilisateur";
+$strings['ValidType']      = "Veuillez sélectionner un type";
+$strings['ValidSubject']   = "Veuillez sélectionner un sujet";
+$strings['ValidCourse']    = "Veuillez sélectionner un cours";
+$strings['ValidEmail']     = "L'adresse e-mail doit être correcte";
+$strings['ValidMessage']   = "Veuillez introduire un message";
+
+$strings['Presential']     = "Présentiel";
+$strings['PersonalEmail']  = "E-mail personnel";
+$strings['Optional']       = "Optionnel";
+$strings['ErrorRegisterMessage'] = "Le ticket n'a pas pu être enregistré";
+$strings['Source']       = "Source";
+

+ 68 - 0
plugin/ticket/lang/spanish.php

@@ -0,0 +1,68 @@
+<?php /* License: see /license.txt */
+//Needed in order to show the plugin title
+$strings['plugin_title']        = "TicketSupport";
+$strings['plugin_comment']      = "Plugin para el soporte de Tickets de atencion sobre Chamilo.";
+
+$strings['TicketNum']        = "Ticket #";
+$strings['Date']             = "Fecha";
+$strings['DateLastEdition']  = "Ultima Edici&oacute;n";
+$strings['Category']      = "Categoria";
+$strings['User']          = "Usuario";
+$strings['Program']       = "Programa";
+$strings['Responsible']   = "Responsable";
+$strings['Status']        = "Estado";
+$strings['Message']       = "Mensajes";
+$strings['Description']   = "Descripcion";
+
+$strings['Tickets']          = "Tickets";
+$strings['MyTickets']        = "Mis Tickets";
+$strings['MsgWelcome']       = "Bienvenido a su secci&oacute;n MIS TICKETS. Esta secci&oacute;n le permite revisar sus Tickets de Soporte generados en SOPORTE TECNICO";
+$strings['TckSuccessSave']   = "Se registró con exito su ticket";
+$strings['TckClose']         = "Cerrar Tickets";
+$strings['TckNew']           = "Nuevo Ticket";
+$strings['TcksNew']          = "Tickets Nuevos";
+$strings['Unassigned']       = "No asignados";
+$strings['Unassign']         = "Desasignado";
+$strings['Read']             = "Leidos";
+$strings['Unread']           = "No Leidos";
+$strings['RegisterDate']     = "Fecha de Registro";
+$strings['Priority']         = "Prioridad";
+$strings['AssignedTo']       = "Asignado a";
+
+$strings['ValidUser']      = "Debe seleccionar a un usuario";
+$strings['ValidType']      = "Debe seleccionar un tipo";
+$strings['ValidSubject']   = "Debe escribir un asunto";
+$strings['ValidCourse']    = "Debe elegir un curso";
+$strings['ValidEmail']     = "Debe digitar un email valido";
+$strings['ValidMessage']   = "Debe escribir un mensaje";
+
+$strings['PersonalEmail']  = "Email Personal";
+$strings['Optional']       = "Opcional";
+$strings['ErrorRegisterMessage'] = "No se pudo registrar su ticket";
+$strings['Source']       = "Fuente";
+$strings['DeniedAccess']   = "Acceso denegado.";
+
+
+// Status Tickets
+$strings['StsNew']         = "Nuevo";
+$strings['StsPending']     = "Pendiente";
+$strings['StsUnconfirmed'] = "Por Confirmar";
+$strings['StsClose']       = "Cerrado";
+$strings['StsReenviado']   = "Reenviado";
+
+// Priority
+$strings['Priority']         = "Prioridad";
+$strings['PriorityHigh']     = "Alta";
+$strings['PriorityNormal']   = "Normal";
+$strings['PriorityLow']      = "Baja";
+
+// Source
+$strings['SrcEmail']         = "Email";
+$strings['SrcPhone']         = "Telefono";
+$strings['SrcPresential']    = "Presencial";
+
+//
+
+$strings['TckAssignedMsg']    = "<p>Estimado(a):</p><p> ? ? </p>
+								<p>Se le ha sido asignado el ticket ? <a href=\"?\">Ticket</a></p>
+							    <p>Mensaje enviado desde el sistema de ticket.</p>";

+ 66 - 0
plugin/ticket/lib/ticket.class.php

@@ -0,0 +1,66 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * This class defines the basis of the ticket management system plugin
+ * @package chamilo.plugin.ticket
+ */
+/**
+ * Ticket class
+ */
+class Ticket {
+
+    var $url;
+    var $salt;
+    var $api;
+    var $user_complete_name = null;
+    var $protocol = 'http://';
+    var $debug = false;
+    var $logout_url = null;
+    var $plugin_enabled = false;
+
+    /**
+     * Constructor (generates a connection to the API and the Chamilo settings
+     * required for the connection to the videoconference server)
+     */
+    function __construct() {
+
+        // initialize video server settings from global settings
+        $plugin = TicketPlugin::create();
+/*
+        $bbb_plugin = $plugin->get('tool_enable');
+        $bbb_host   = $plugin->get('host');
+        $bbb_salt   = $plugin->get('salt');
+
+        //$course_code = api_get_course_id();
+
+        $this->logout_url = api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php';
+        $this->table = Database::get_main_table('plugin_bbb_meeting');
+
+        if ($bbb_plugin == true) {
+            $user_info = api_get_user_info();
+            $this->user_complete_name = $user_info['complete_name'];
+            $this->salt = $bbb_salt;
+            $info = parse_url($bbb_host);
+            $this->url = $bbb_host.'/bigbluebutton/';
+            if (isset($info['scheme'])) {
+                $this->protocol = $info['scheme'].'://';
+                $this->url = str_replace($this->protocol, '', $this->url);
+            }
+
+            // Setting BBB api
+            define('CONFIG_SECURITY_SALT', $this->salt);
+            define('CONFIG_SERVER_BASE_URL', $this->url);
+
+            $this->api = new TckBlueButtonBN();
+            $this->plugin_enabled = true;
+        }*/
+    }
+    /**
+     * Checks whether a user is teacher in the current course
+     * @return bool True if the user can be considered a teacher in this course, false otherwise
+     */
+    function is_teacher() {
+        return api_is_course_admin() || api_is_coach() || api_is_platform_admin();
+    }
+
+}

+ 98 - 0
plugin/ticket/lib/ticket_plugin.class.php

@@ -0,0 +1,98 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Class TicketPlugin definition file
+ * @package chamilo.plugin.ticket
+ */
+/**
+ * Class TicketPlugin
+ */
+class TicketPlugin extends Plugin
+{
+    static function create() {
+        static $result = null;
+        return $result ? $result : $result = new self();
+    }
+
+    protected function __construct() {
+        parent::__construct('1.0', 'Kenny Rodas Chavez', array('tool_enable' => 'boolean'));
+    }
+
+    function install() {
+        // Create database tables
+        require_once api_get_path(SYS_PLUGIN_PATH).PLUGIN_NAME.'/database.php';
+
+        // Create link tab
+        $homep = api_get_path(SYS_PATH).'home/'; //homep for Home Path
+        $menutabs = 'home_tabs'; //menutabs for tabs Menu
+        $menuf = $menutabs;
+        $ext = '.html'; //ext for HTML Extension - when used frequently, variables are faster than hardcoded strings
+        $lang = ''; //el for "Edit Language"
+        if (!empty($_SESSION['user_language_choice'])) {
+            $lang = $_SESSION['user_language_choice'];
+        } elseif (!empty($_SESSION['_user']['language'])) {
+            $lang = $_SESSION['_user']['language'];
+        } else {
+            $lang = api_get_setting('platformLanguage');
+        }
+        $link_url = api_get_path(WEB_PLUGIN_PATH).'ticket/s/myticket.php';
+
+        $home_menu = '<li class="show_menu"><a href="'.$link_url.'" target="_self"><span>Ticket</span></a></li>';
+
+        // Write
+        if (file_exists($homep.$menuf.'_'.$lang.$ext)) {
+            if (is_writable($homep.$menuf.'_'.$lang.$ext)) {
+                $fp = fopen($homep.$menuf.'_'.$lang.$ext, 'w');
+                fputs($fp, $home_menu);
+                fclose($fp);
+                if (file_exists($homep.$menuf.$ext)) {
+                    if (is_writable($homep.$menuf.$ext)) {
+                        $fpo = fopen($homep.$menuf.$ext, 'w');
+                        fputs($fpo, $home_menu);
+                        fclose($fpo);
+                    }
+                }
+            } else {
+                $errorMsg = get_lang('HomePageFilesNotWritable');
+            }
+        } else {
+            //File does not exist
+            $fp = fopen($homep.$menuf.'_'.$lang.$ext, 'w');
+            fputs($fp, $home_menu);
+            fclose($fp);
+        }
+
+    }
+
+    function uninstall() {
+        $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
+        $t_options = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
+        $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
+
+        //Delete settings
+        $sql = "DELETE FROM $t_settings WHERE variable = 'ticket_tool_enable'";
+        Database::query($sql);
+
+        $sql = "DROP TABLE IF EXISTS ticket_ticket";
+        Database::query($sql);
+        $sql = "DROP TABLE IF EXISTS ticket_status";
+        Database::query($sql);
+        $sql = "DROP TABLE IF EXISTS ticket_project";
+        Database::query($sql);
+        $sql = "DROP TABLE IF EXISTS ticket_priority";
+        Database::query($sql);
+        $sql = "DROP TABLE IF EXISTS ticket_message_attch";
+        Database::query($sql);
+        $sql = "DROP TABLE IF EXISTS ticket_message";
+        Database::query($sql);
+        $sql = "DROP TABLE IF EXISTS ticket_category";
+        Database::query($sql);
+        $sql = "DROP TABLE IF EXISTS ticket_assigned_log";
+        Database::query($sql);
+        $sql = "DROP TABLE IF EXISTS ticket_ticket";
+        Database::query($sql);
+
+        //Deleting course settings
+        $this->uninstall_course_fields_in_all_courses();
+    }
+}

+ 4 - 0
plugin/ticket/plugin.php

@@ -0,0 +1,4 @@
+<?php
+/* For licensing terms, see /license.txt */
+require_once dirname(__FILE__).'/config.php';
+$plugin_info = TicketPlugin::create()->get_info();

+ 1 - 0
plugin/ticket/readme.txt

@@ -0,0 +1 @@
+This plugin provides the support ticket management system features

+ 46 - 0
plugin/ticket/s/assign_tickets.php

@@ -0,0 +1,46 @@
+<?php
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+api_protect_course_script();
+if (!api_is_allowed_to_edit()){
+	api_not_allowed();
+}
+$course_info = api_get_course_info();
+$course_code = $course_info['code'];
+    echo '<form action="tutor.php" name="asignar" id ="asignar">';
+    echo '<div id="confirmacion"></div>';
+    $id = $_GET['id'];
+    $table_reporte_semanas = Database::get_main_table('rp_reporte_semanas');
+    $sql ="SELECT * FROM $table_reporte_semanas WHERE id = '$id'";
+    $sql_tareas = "SELECT id AS colid, title as coltitle FROM ".Database::get_course_table(TABLE_STUDENT_PUBLICATION , $course_info['dbName'])." WHERE parent_id = 0
+        		   AND id NOT IN (SELECT work_id FROM $table_reporte_semanas WHERE course_code = '$course_code' AND id != '$id')";
+    $sql_foros = "SELECT thread_id AS colid, thread_title AS coltitle FROM ".Database::get_course_table(TABLE_FORUM_THREAD, $course_info['dbName'])."
+    			  WHERE thread_id NOT IN (SELECT forum_id FROM $table_reporte_semanas WHERE course_code = '$course_code' AND id != '$id')";
+    $rs = Database::fetch_object(Database::query($sql));
+    $result_tareas = Database::query($sql_tareas);
+    $result_foros = Database::query($sql_foros);
+
+   echo '<div class="row">
+   		<input type="hidden" id="rs_id" name ="rs_id" value="'.$id.'">
+    	<div class="formw">Seleccione la Tarea</div>	
+    	</div>';
+    echo '<div class="row"><div class="formw"><select name ="work_id" id="work_id">';
+    	echo '<option value="0"'.(($row['colid']==$rs->work_id)?"selected":"").'>'.'Seleccione'.'</option>';
+    	while($row = Database::fetch_assoc($result_tareas)){
+    		echo '<option value="'.$row['colid'].'"'.(($row['colid']==$rs->work_id)?"selected":"").'>'.$row['coltitle'].'</option>';
+    	}
+    echo '</select></div><div>';
+    echo '<div class="row">
+    	<div class="formw">Seleccione el tema</div>
+    	</div>';
+    echo '<div class="row"><div class="formw"><select name ="forum_id" id="forum_id">';
+    echo '<option value="0"'.(($row['colid']==$rs->work_id)?"forum_id":"").'>'.'Seleccione'.'</option>';    
+    while($row = Database::fetch_assoc($result_foros)){
+    	echo '<option value="'.$row['colid'].'"'.(($row['colid']==$rs->forum_id)?"selected":"").'>'.$row['coltitle'].'</option>';
+    }
+    echo '</select></div><div>';
+    echo '<div class="row">
+    		<div class="formw"><button class="save" name="editar" type="button" value="Editar" onClick="save('."$id".');">Editar</button></div>	
+    	  </div>';
+  	echo '</form>';

+ 27 - 0
plugin/ticket/s/course_user_list.php

@@ -0,0 +1,27 @@
+<?php
+$language_file = array('registration');
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+$user_id=intval($_GET['user_id']);
+$user_info = api_get_user_info($user_id);
+$courses_list=CourseManager::get_courses_list_by_user_id($user_id,false,true);
+?>
+<div class="row">
+	<div class="label2"><?php echo get_lang('User')?>:</div>
+       <div class="formw2" id="user_request"><?php echo $user_info['firstname']." ".$user_info['lastname'] ;?></div>
+</div>
+<div class="row" id="divCourse">
+	<div class="label2"><?php echo get_lang('Course')?>:</div>
+	<div class="formw2" id="courseuser">
+	 <select  class="chzn-select" name = "course_id" id="course_id"  style="width:95%;">
+		<option value="0">---<?php echo get_lang('Select')?>---</option>
+		<?php
+		foreach ($courses_list as $key => $course) {
+			$courseinfo = CourseManager::get_course_information($course['code']);
+			echo '<option value="'. $courseinfo['code'].'"> '.$courseinfo['title'].'</option>';
+		}
+		?>
+	</select>
+	</div>
+</div>

+ 42 - 0
plugin/ticket/s/download.php

@@ -0,0 +1,42 @@
+<?php
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+require_once api_get_path(LIBRARY_PATH).'group_portal_manager.lib.php';
+require_once api_get_path(LIBRARY_PATH).'document.lib.php';
+
+api_block_anonymous_users();
+$language_file = array('courses', 'index','admin');
+$user_id = api_get_user_id();
+if(!isset($_GET['file']) || ! isset($_GET['title']) || !isset($_GET['ticket_id'])){
+	api_not_allowed();
+}
+if(!api_is_platform_admin()){	
+	$ticket_id = $_GET['ticket_id'];
+	$table_support_messages = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+	$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+	$table_support_message_attachments = Database::get_main_table(TABLE_SUPPORT_MESSAGE_ATTACHMENTS);
+	$sql ="SELECT DISTINCT  ticket.request_user FROM  $table_support_tickets ticket, $table_support_messages message,  $table_support_message_attachments attch 
+			WHERE ticket.ticket_id = message.ticket_id  AND attch.message_id = message.message_id  AND ticket.ticket_id = $ticket_id";
+	$rs           = Database::query($sql);
+	$row_users    = Database::fetch_array($rs, 'ASSOC');
+	$user_request_id = $row_users['request_user'];
+	if(intval($user_request_id) != $user_id ){
+		api_not_allowed();
+	}
+	
+}
+$file_url = $_GET['file'];
+$file_url = str_replace('///', '&', $file_url);
+$file_url = str_replace(' ', '+', $file_url);
+$file_url = str_replace('/..', '', $file_url); 
+$file_url = Database::escape_string($file_url);
+$title = $_GET['title'];
+$path_attachment = api_get_path(SYS_PATH);
+$path_message_attach =$path_attachment.'tck_messageattch/';
+$full_file_name = $path_message_attach.$file_url;
+if (Security::check_abs_path($full_file_name, $path_message_attach)) {
+	DocumentManager::file_send_for_download($full_file_name,TRUE, $title);
+}
+
+exit;

+ 4 - 0
plugin/ticket/s/index.php

@@ -0,0 +1,4 @@
+<?php
+require_once '../config.php';
+header('location:'.api_get_path(WEB_PLUGIN_PATH).PLUGIN_NAME.'/s/myticket.php?message=success');
+?>

+ 293 - 0
plugin/ticket/s/myticket.php

@@ -0,0 +1,293 @@
+<?php
+$language_file= array('messages','userInfo', 'admin');
+$cidReset	= true;
+
+$course_plugin = 'ticket'; //needed in order to load the plugin lang variables
+require_once '../config.php';
+
+$plugin = TicketPlugin::create();
+$tool_name = $plugin->get_lang('DateLastEdition');
+
+api_block_anonymous_users();
+require_once api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php';
+require_once api_get_path(LIBRARY_PATH).'group_portal_manager.lib.php';
+$htmlHeadXtra[] = '<script type="text/javascript">
+function load_history_ticket (div_course,ticket_id) {
+	 $.ajax({
+		contentType: "application/x-www-form-urlencoded",
+		beforeSend: function(object) {
+		$("div#"+div_course).html("<img src=\'../../../main/inc/lib/javascript/indicator.gif\' />"); },
+		type: "POST",
+		url: "ticket_assign_log.php",
+		data: "ticket_id="+ticket_id,
+		success: function(data) {
+			$("div#div_"+ticket_id).html(data);
+			$("div#div_"+ticket_id).attr("class","blackboard_show");
+			$("div#div_"+ticket_id).attr("style","");
+		}
+	});
+}
+function clear_course_list (div_course) {
+	$("div#"+div_course).html("&nbsp;");
+	$("div#"+div_course).hide("");
+}
+		
+	$(function() {
+    	$( "#keyword_start_date_start" ).datepicker({ dateFormat: '."'dd/mm/yy'".' });
+    	$( "#keyword_start_date_end" ).datepicker({ dateFormat: '."'dd/mm/yy'".' });
+  	});
+  	
+	$(document).ready(function() {
+		$("#advanced_search_form").css("display","none");
+	});
+	
+	function display_advanced_search_form () {
+	    if ($("#advanced_search_form").css("display") == "none") {
+	                $("#advanced_search_form").css("display","block");
+	                $("#img_plus_and_minus").html(\'&nbsp;'.Display::return_icon('div_hide.gif',get_lang('Hide'),array('style'=>'vertical-align:middle')).'&nbsp;'.get_lang('AdvancedSearch').'\');
+	        } else {
+	                $("#advanced_search_form").css("display","none");
+	                $("#img_plus_and_minus").html(\'&nbsp;'.Display::return_icon('div_show.gif',get_lang('Show'),array('style'=>'vertical-align:middle')).'&nbsp;'.get_lang('AdvancedSearch').'\');
+	        }
+	}
+</script>
+<style>
+div.row div.label2 {
+	float:left;
+	width:35%;
+	text-align: left;
+}
+div.row div.formw2 {
+    width:65%;
+	float:left;
+}
+.blackboard_show {
+	float:left;
+	position:absolute;
+	border:1px solid black;
+	width: 350px;
+	background-color:white;
+	z-index:99; padding: 3px;
+	display: inline;
+}
+.blackboard_hide {
+	display: none;
+}
+</style>';
+
+$this_section = 'tickets';
+unset($_SESSION['this_section']);
+
+$table = new SortableTable('Tickets', array('TicketManager', 'get_total_tickets_by_user_id'), array('TicketManager', 'get_tickets_by_user_id') ,  2,  20, 'DESC');
+if ($table->per_page == 0){
+	$table->per_page = 20;
+}
+
+if(isset($_GET['action'])){
+	global $table;
+	$action = $_GET['action'];
+	switch ($action){
+		case 'assign':
+			if($isAdmin && isset($_GET['ticket_id']) )
+				TicketManager::assign_ticket_user($_GET['ticket_id'], $user_id);				
+				break;
+		case 'unassign':
+			if($isAdmin && isset($_GET['ticket_id']) )
+				TicketManager::assign_ticket_user($_GET['ticket_id'], 0);
+				break;
+		case 'alert':
+			if(!$isAdmin && isset($_GET['ticket_id']) )
+				TicketManager::send_alert($_GET['ticket_id'],$user_id);
+				break;
+		case 'export':
+			$data = array( array( $plugin->get_lang('TicketNum'), $plugin->get_lang('Date'), $plugin->get_lang('DateLastEdition'), $plugin->get_lang('Category'), $plugin->get_lang('User'), $plugin->get_lang('Program'), $plugin->get_lang('Responsible'), $plugin->get_lang('Status'), $plugin->get_lang('Message'), $plugin->get_lang('Description') ) );
+			$datos = $table->get_clean_html();
+			foreach ($datos as $ticket){
+				$ticket[0] = substr(strip_tags($ticket[0]), 0,12);
+				$ticket_rem = array(utf8_decode( strip_tags($ticket[0])), utf8_decode(api_html_entity_decode($ticket[1])), utf8_decode(strip_tags($ticket[2])), utf8_decode(strip_tags($ticket[3])), utf8_decode(strip_tags($ticket[4])), utf8_decode(strip_tags($ticket[5])), utf8_decode(strip_tags($ticket[6])), utf8_decode(strip_tags($ticket[7])), utf8_decode(strip_tags($ticket[8])), utf8_decode(strip_tags($ticket[10])) );
+				$data[] = $ticket_rem;
+			}
+			Export::export_table_xls($data, $plugin->get_lang('Tickets'));
+			exit;
+			break;
+		case 'close_tickets':
+			TicketManager::close_old_tickets();
+			break;
+		default:
+			break;
+	}
+}
+//$nameTools = api_xml_http_response_encode($plugin->get_lang('MyTickets'));
+$user_id = api_get_user_id();
+$isAdmin = api_is_platform_admin();
+
+Display::display_header($plugin->get_lang('MyTickets'));
+if ($isAdmin){
+	$get_parameter  = '&keyword='. $_GET['keyword'] .'&keyword_status='. $_GET['keyword_status'] .'&keyword_category='. $_GET['keyword_category'] .'&keyword_request_user='. $_GET['keyword_request_user'];
+	$get_parameter .= '&keyword_admin='. $_GET['keyword_admin'] .'&keyword_start_date='. $_GET['keyword_start_date'].'&keyword_unread='. $_GET['keyword_unread'] ;
+	$get_parameter2 = '&Tickets_per_page='.$_GET['Tickets_per_page'].'&Tickets_column='.$_GET['Tickets_column'];
+	if (isset($_GET['submit_advanced'])){
+		$get_parameter .= "&submit_advanced=";
+	}
+	if (isset($_GET['submit_simple'])){
+		$get_parameter .= "&submit_simple=";
+	}
+	//select categories
+	$select_types .= '<select class="chzn-select" style="width: 200px; "  name = "keyword_category" id="keyword_category" ">';
+	$select_types .= '<option value="">---'.get_lang('Select').'---</option>';
+	$types = TicketManager::get_all_tickets_categories();
+	foreach ($types as $type) {
+		$select_types.= "<option value = '".$type['category_id']."'>".$type['name']."</option>";
+	}
+	$select_types .= "</select>";
+	//select admins
+	$select_admins .= '<select  class ="chzn-select" style="width: 200px; " name = "keyword_admin" id="keyword_admin" ">';
+	$select_admins .= '<option value="">---'.get_lang('Select').'---</option>';
+	$select_admins .= '<option value = "0">'.$plugin->get_lang('Unassigned').'</option>';
+	$admins = UserManager::get_user_list_like(array("status"=>"1"),array("username"),true);
+	foreach ($admins as $admin) {
+		$select_admins.= "<option value = '".$admin['user_id']."'>".$admin['lastname']." ,".$admin['firstname']."</option>";
+	}
+	$select_admins .= "</select>";
+	//select status
+	$select_status .= '<select  class ="chzn-select" style="width: 200px; " name = "keyword_status" id="keyword_status" >';
+	$select_status .= '<option value="">---'.get_lang('Select').'---</option>';
+	$status = TicketManager::get_all_tickets_status();
+	foreach ($status as $stat) {
+		$select_status.= "<option value = '".$stat['status_id']."'>".$stat['name']."</option>";
+	}
+	$select_status .= "</select>"; 
+	//select priority
+	$select_priority .= '<select  style="width: 200px; " name = "keyword_priority" id="keyword_priority" >';
+	$select_priority .= '<option value="">'.get_lang('All').'</option>';
+	$select_priority .= '<option value="NRM">'.get_lang('PriorityNormal').'</option>';
+	$select_priority .= '<option value="ALT">'.get_lang('PriorityHigh').'</option>';
+	$select_priority .= '<option value="LOW">'.get_lang('PriorityLow').'</option>';
+	$select_priority .= "</select>"; 
+	
+	//select unread
+	$select_unread = '<select  style="width: 100px; " name = "keyword_unread" id="keyword_unread" >';
+	$select_unread .= '<option value="">'.get_lang('All').'</option>';
+	$select_unread .= '<option value="yes">'.get_lang('Read').'</option>';
+	$select_unread .= '<option value="no">'.get_lang('Unread').'</option>';
+	$select_unread .= "</select>";
+	// Create a search-box
+	$form = new FormValidator('search_simple','get','','',null,false);
+	$renderer =& $form->defaultRenderer();
+	$renderer->setElementTemplate('<span>{element}</span> ');
+	$form->addElement('text','keyword',get_lang('keyword'), 'size="25"');
+	$form->addElement('style_submit_button', 'submit_simple',get_lang('Search'),'class="search"');
+	$form->addElement('static','search_advanced_link',null,'<a href="javascript://" class = "advanced_parameters" onclick="display_advanced_search_form();"><span id="img_plus_and_minus">&nbsp;'.Display::return_icon('div_show.gif',get_lang('Show'),array('style'=>'vertical-align:middle')).' '.get_lang('AdvancedSearch').'</span></a>');
+	
+	echo '<div class="actions" style="width:100%;">';
+	if (api_is_platform_admin()) {
+		/*echo '<span style="float:right;">'.
+				'<a href="'.api_get_self().'?action=close_tickets">'.Display::return_icon('warning.png',$plugin->get_lang('TckClose'),'','32').'</a>'.
+				'</span>';*/
+		echo '<span style="float:right;">'.
+				'<a href="'.api_get_self().'?action=export'.$get_parameter.$get_parameter2.'">'.Display::return_icon('import_excel.png',get_lang('Export'),'','32').'</a>'.
+				'</span>';
+		echo '<span style="float:right;">'.
+				'<a href="'.api_get_path(WEB_PLUGIN_PATH).'ticket/s/new_ticket.php">'.Display::return_icon('add.png',$plugin->get_lang('TckNew'),'','32').'</a>'.
+				'</span>';	
+		echo '<span style="float:right;">'.
+				'</span>';
+	}
+	$form->display();
+	echo '</div>';
+	echo '<form action="'.api_get_self().'" method="get" name="advanced_search" id="advanced_search" display:"none">
+			<div id="advanced_search_form" style="display: block;">
+				<div class="row">
+					<div class="form_header">'.get_lang('AdvancedSearch').'</div>
+				</div>
+				<table width="100%">
+					<tbody>
+						<tr>
+							<td width="30%"><div class="row">
+								<div class="label2">'.get_lang('Category').'</div>
+								<div class="formw2">'.$select_types.'</div>
+							</div></td>
+							<td width="25%"><div class="row">
+								<div class="label2">'.get_lang('User').'</div>
+								<div class="formw2"><input id="keyword_request_user" name="keyword_request_user" type="text"></div>
+							</div></td>
+							<td width="25%"><div class="row">
+								<div class="label2">'.$plugin->get_lang('RegisterDate').':</div>
+								<div class="formw2"><input id="keyword_start_date_start" name="keyword_start_date_start" type="text"></div>
+							</div></td>
+							<td width="20%"><div class="row">
+								<div class="label2"><input type="checkbox" name="keyword_dates" value="1">'.get_lang('Untill').':</div>
+								<div class="formw2"><input id="keyword_start_date_end" name="keyword_start_date_end" type="text"></div>
+							</div></td>
+						</tr>
+						<tr >
+							<td><div class="row">
+								<div class="label2">'.$plugin->get_lang('AssignedTo').':</div>
+								<div class="formw2">'.$select_admins.'</div>
+							</div></td>
+							<td><div class="row">
+								<div class="label2">'.get_lang('Status').':</div>
+								<div class="formw2">'.$select_status.'</div>
+							</div></td>
+							<td><div class="row">
+								<div class="row">
+								<div class="label2">'.$plugin->get_lang('Priority').':</div>
+								<div class="formw2">'.$select_priority.'</div>
+							</div></td>
+							<td><div class="row">
+								<div class="row">
+								<div class="label2">'.$plugin->get_lang('Priority').':</div>
+								<div class="formw2">'.$select_unread.'</div>
+							</div></td>
+							
+						</tr>
+						<tr>
+							<td width="30%">
+								<div class="row" >
+									<div class="label2">'.get_lang('Course').'</div>
+									<div class="formw2"><input id="keyword_course" name="keyword_course" type="text"></div>
+								</div>
+							</td>
+							<td colspan= "3"><div class="row">
+										<button  name="submit_advanced" type="submit">'.get_lang('AdvancedSearch').'</button>
+							</div></td>
+						</tr>
+					</tbody>
+				</table>
+			</div>
+			<input name="_qf__advanced_search" type="hidden" value="">
+				<div class="clear">&nbsp;</div>
+			</form>
+					';
+	
+}
+
+
+if($isAdmin){
+	$table->set_header(0, $plugin->get_lang('TicketNum'), true);
+	$table->set_header(1, $plugin->get_lang('Date'), true);
+	$table->set_header(2, $plugin->get_lang('DateLastEdition'), true);
+	$table->set_header(3, $plugin->get_lang('Category'), true);
+	$table->set_header(4, $plugin->get_lang('User'), true);
+	$table->set_header(5, $plugin->get_lang('Responsible'), true);
+	$table->set_header(6, $plugin->get_lang('Status'), true);
+	$table->set_header(7, $plugin->get_lang('Message'), true);
+	$table->set_header(8, get_lang('Actions'), true);
+	$table->set_header(9, get_lang('Description'), true,array("style"=>"width:200px"));
+}else{
+	echo '<center><h1>'.$plugin->get_lang('MyTickets').'</h1></center>';
+	echo '<center><p>'.$plugin->get_lang('MsgWelcome').'</p></center>';
+	if(isset($_GET['message'])){
+		Display::display_confirmation_message($plugin->get_lang('TckSuccessSave'));
+	}
+	$table->set_header(0, $plugin->get_lang('TicketNum'), true);
+	$table->set_header(1, $plugin->get_lang('Date'), true);
+	$table->set_header(2, $plugin->get_lang('DateLastEdition'), true);
+	$table->set_header(3, $plugin->get_lang('Category'));
+	$table->set_header(4, $plugin->get_lang('Status'), false);
+	$table->set_header(5, get_lang('Actions'), false);
+}
+
+$table->display();
+Display::display_footer();
+?>

+ 447 - 0
plugin/ticket/s/new_ticket.php

@@ -0,0 +1,447 @@
+<?php
+/*    INIT SECTION   */
+$language_file = array('messages','userInfo', 'admin');
+$cidReset = true;
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+api_block_anonymous_users();
+require_once api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php';
+require_once api_get_path(LIBRARY_PATH).'group_portal_manager.lib.php';
+
+$htmlHeadXtra[]='
+<script>
+$(document).ready(function(){
+	document.getElementById("divEmail").style.display="none";
+});
+function load_course_list (div_course,my_user_id) {
+	 $.ajax({
+		contentType: "application/x-www-form-urlencoded",
+		type: "GET",
+		url: "course_user_list.php",
+		data: "user_id="+my_user_id,
+		success: function(datos) {
+			$("div#user_request").html(datos);		
+			$("#user_id_request").val(my_user_id);
+			$("#btnsubmit").attr("disabled", false);
+		}
+	});
+}
+function changeType() {
+var selected = document.getElementById("category_id").selectedIndex;
+var id = document.getElementById("category_id").options[selected].value  ;
+	document.getElementById("project_id").value= projects[id];
+	document.getElementById("other_area").value= other_area[id];
+	document.getElementById("email").value= email[id];
+	document.getElementById("divEmail").style.display="none";
+	if(parseInt(course_required[id]) == 0){
+		document.getElementById("divCourse").style.display="none";		
+		if( id != "CUR"){
+			document.getElementById("divEmail").style.display="";
+			document.getElementById("personal_email").required="required";	
+		}			
+		document.getElementById("course_id").disabled=true;	
+		document.getElementById("course_id").value=0;			
+	}else{	
+		document.getElementById("divCourse").style.display = "";
+		document.getElementById("course_id").disabled=false;
+		document.getElementById("course_id").value=0;
+		document.getElementById("personal_email").value="";
+	}
+}
+function handleClick2(myRadio) {
+	var user_id = myRadio.value;
+	document.getElementById("user_id_request").value = user_id;
+	alert(document.getElementById("user_id_request").value);
+}
+function validate() {
+	var re  = /^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/; 
+	fckEditor1val = FCKeditorAPI.__Instances["content"].GetHTML();
+	document.getElementById("content").value= fckEditor1val;
+	var selected = document.getElementById("category_id").selectedIndex;
+	var id = document.getElementById("category_id").options[selected].value;
+	if(document.getElementById("user_id_request").value == ""){
+		alert("'.$plugin->get_lang("ValidUser").'");
+		return false;
+	}else if( id == 0){
+		alert("'.$plugin->get_lang("ValidType").'");
+		return false;
+	}else if(document.getElementById("subject").value == ""){
+		alert("'.$plugin->get_lang("ValidSubject").'");
+		return false;
+	}else if(parseInt(course_required[id]) == 1 && document.getElementById("course_id").value == 0){
+		alert("'.$plugin->get_lang("ValidCourse").'");
+		return false;
+	}else if(id !="CUR" && parseInt(course_required[id]) != 1  && !re.test(document.getElementById("personal_email").value)){
+		alert("'.$plugin->get_lang("ValidEmail").'");
+		return false;
+	}else if(fckEditor1val ==""){
+		alert("'.$plugin->get_lang("ValidMessage").'");
+		return false;
+	}
+}
+
+var counter_image = 1;
+function remove_image_form(id_elem1) {
+	var elem1 = document.getElementById(id_elem1);
+	elem1.parentNode.removeChild(elem1);
+	counter_image = counter_image - 1;
+}
+function add_image_form() {
+	// Multiple filepaths for image form
+	var filepaths = document.getElementById("filepaths");
+	if (document.getElementById("filepath_"+counter_image)) {
+		counter_image = counter_image + 1;
+	}  else {
+		counter_image = counter_image;
+	}
+	var elem1 = document.createElement("div");
+	elem1.setAttribute("id","filepath_"+counter_image);
+	filepaths.appendChild(elem1);
+	id_elem1 = "filepath_"+counter_image;
+	id_elem1 = "\'"+id_elem1+"\'";
+	document.getElementById("filepath_"+counter_image).innerHTML = "<input type=\"file\" name=\"attach_"+counter_image+"\"  size=\"20\" />&nbsp;<a href=\"javascript:remove_image_form("+id_elem1+")\"><img src=\"'.api_get_path(WEB_CODE_PATH).'img/delete.gif\"></a>";
+	//document.getElementById("filepath_"+counter_image).innerHTML = "<input type=\"file\" name=\"attach_"+counter_image+"\"  size=\"20\" />&nbsp;<input type=\"text\" name=\"legend[]\" size=\"20\" />";
+	if (filepaths.childNodes.length == 6) {
+		var link_attach = document.getElementById("link-more-attach");
+		if (link_attach) {
+			link_attach.innerHTML="";
+		}
+	}
+}
+</script>
+
+<style>
+div.row div.label2 {
+	float:left;
+	width:10%;
+}
+div.row div.formw2 {
+    width:90%;
+	float:left
+}
+div.divTicket {
+    width: 70%;
+	float: center;
+	margin-left: 15%;
+	
+}
+</style>';
+$types = TicketManager::get_all_tickets_categories();
+$htmlHeadXtra[] = '<script language="javascript">
+		var projects = '.js_array($types,'projects','project_id'). '
+		var course_required = '.js_array($types,'course_required','course_required').'
+		var other_area = '.js_array($types,'other_area','other_area').'
+		var email = '.js_array($types,'email','email').'
+		 </script>';
+$htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
+$htmlHeadXtra[] = '<link  href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
+
+function js_str($s) {
+	return '"'.addcslashes($s, "\0..\37\"\\").'"';
+}
+
+function js_array($array,$name,$key) {
+	$temp=array();
+	$return = "new Array(); ";
+	foreach ($array as $value){
+		$return .= $name."['".$value['category_id']."'] ='".$value[$key]."'; ";
+	}
+	return $return;
+}
+
+function show_form_send_ticket(){
+	global $types, $plugin;
+	echo '<div class="divTicket">';
+	echo '<form enctype="multipart/form-data" action="'.api_get_self().'" method="post" name="send_ticket" id="send_ticket"
+ 	onsubmit="return validate()" style="width:100%">';
+	echo '<input name="user_id_request" id="user_id_request" type="hidden" value="">';
+	
+	// Category
+	$select_types = '<div class="row">
+	<div class="label2">'.get_lang('Category').': </div>
+       <div class="formw2">';
+	$select_types .= '<select style="width: 95%; "   name = "category_id" id="category_id" onChange="changeType();">';
+	$select_types .= '<option value="0">---'.get_lang('Select').'---</option>';
+	foreach ($types as $type) {
+		$select_types.= "<option value = '".$type['category_id']."'>".$type['name'].":  <br/>".$type['description']."</option>";
+	}
+	$select_types .= "</select>";
+	$select_types .= '</div></div>';
+	echo $select_types;
+	
+	// Course
+	$courses_list = CourseManager::get_courses_list_by_user_id($user_id,false,true);
+	 $select_course = '<div id="user_request" >
+	 </div>';
+	echo $select_course;
+	
+	// Status
+	$status = array();
+	$status[NEWTCK] = $plugin->get_lang('StsNew');
+	$status[PENDING] = $plugin->get_lang('StsPending');
+	$status[UNCONFIRMED] = $plugin->get_lang('StsUnconfirmed');
+	$status[CLOSE] = $plugin->get_lang('StsClose');
+	$status[REENVIADO] = $plugin->get_lang('StsReenviado');
+	$select_status = '
+	<div class="row"  >
+		<div class="label2"  >'.get_lang('Status').': </div>
+		<div class="formw2">
+			<select style="width: 95%; " name = "status_id" id="status_id">';
+	//$status = TicketManager::get_all_tickets_status();
+	foreach ($status as $sts_key => $sts_name) {
+		if($sts_key=='PND'){
+			$select_status .=  "<option value = '".$sts_key."' selected >".$sts_name."</option>";
+		}else{
+			$select_status.= "<option value = '".$sts_key."'>".$sts_name."</option>";
+		}
+	}
+	$select_status .= '
+			</select>
+		</div>
+	</div>';
+	echo $select_status;
+	
+	// Source
+	$source = array();
+	$source[SRC_EMAIL] = $plugin->get_lang('SrcEmail');
+	$source[SRC_PHONE] = $plugin->get_lang('SrcPhone');
+	$source[SRC_PRESC] = $plugin->get_lang('SrcPresential');
+	$select_source = '
+	<div class="row">
+	<div class="label2">'.$plugin->get_lang('Source').':</div>
+       <div class="formw2">
+			<select style="width: 95%; " name="source_id" id="source_id" >';
+	foreach ($source as $src_key => $src_name) {
+		$select_source.= "<option value = '".$src_key."'>".$src_name."</option>";
+	}
+	$select_source .='
+			</select>
+		</div>
+	</div>';
+	echo $select_source;
+	
+	// Subject
+	echo '<div class="row" ><div class ="label2">'.get_lang('Subject').':</div>
+       		<div class="formw2"><input type = "text" id ="subject" name="subject" value="" required ="" style="width:94%"/></div>
+		  </div>';
+	
+	// Email
+	echo '<div class="row" id="divEmail" ><div class ="label2">'.$plugin->get_lang('PersonalEmail').':</div>
+       		<div class="formw2"><input type = "email" id ="personal_email" name="personal_email" value=""  style="width:94%"/></div>
+		  </div>';
+	echo '<input name="project_id" id="project_id" type="hidden" value="">';
+	echo '<input name="other_area" id="other_area" type="hidden" value="">';
+	echo '<input name="email" id="email" type="hidden" value="">';
+	
+	// Message
+	echo '<div class="row">
+		<div class="label2">'.get_lang('Message').'</div>
+		<div class="formw2">
+			<input type="hidden" id="content" name="content" value="" style="display:none">
+		<input type="hidden" id="content___Config" value="ToolbarSet=Messages&amp;Width=95%25&amp;Height=250&amp;ToolbarSets={ %22Messages%22: [  [ %22Bold%22,%22Italic%22,%22-%22,%22InsertOrderedList%22,%22InsertUnorderedList%22,%22Link%22,%22RemoveLink%22 ] ], %22MessagesMaximized%22: [  ] }&amp;LoadPlugin=[%22customizations%22]&amp;EditorAreaStyles=body { background: #ffffff; }&amp;ToolbarStartExpanded=false&amp;CustomConfigurationsPath=/main/inc/lib/fckeditor/myconfig.js&amp;EditorAreaCSS=/main/css/chamilo/default.css&amp;ToolbarComboPreviewCSS=/main/css/chamilo/default.css&amp;DefaultLanguage=es&amp;ContentLangDirection=ltr&amp;AdvancedFileManager=true&amp;BaseHref='.api_get_path(WEB_PLUGIN_PATH).PLUGIN_NAME.'/s/&amp;&amp;UserIsCourseAdmin=true&amp;UserIsPlatformAdmin=true" style="display:none">
+		<iframe id="content___Frame" src="/main/inc/lib/fckeditor/editor/fckeditor.html?InstanceName=content&amp;Toolbar=Messages" width="95%" height="250" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border: 0px; background-color: transparent; background-image: none; width: 95%; height: 250px;">
+		</iframe>
+		</div>
+	</div>';
+	
+	// Phone
+	echo '<div class="row" ><div class ="label2">'.get_lang('Phone').' ('.$plugin->get_lang('Optional').'):</div>
+       		<div class="formw2"><input type = "text" id ="phone" name="phone" value="" onkeyup="valid(this,'."'allowspace'".')" onblur="valid(this,'."'allowspace'".')" style="width:94%"/></div>
+		  </div>';
+	
+	// Priority
+	$select_priority = '<div class="row"  >
+	<div class="label2"  >'.$plugin->get_lang('Priority').': </div>
+	<div class="formw2">';
+	
+	$priority = array();
+	$priority[NORMAL] = $plugin->get_lang('PriorityNormal');
+	$priority[HIGH] = $plugin->get_lang('PriorityHigh');
+	$priority[LOW] = $plugin->get_lang('PriorityLow');
+	
+	$select_priority .= '<select style="width: 85px; " name = "priority_id" id="priority_id">';
+	foreach ($priority as $prty_key => $prty_name) {
+		if($sts_key== NORMAL){
+			$select_priority .=  "<option value = '".$prty_key."' selected >".$prty_name."</option>";
+		}else{
+			$select_priority.= "<option value = '".$prty_key."'>".$prty_name."</option>";
+		}
+	}
+	$select_priority .= "</select>";
+	$select_priority .= '</div></div>';
+	echo $select_priority;
+	
+	// Input file attach
+	echo '<div class="row">
+		<div class="label2">'.get_lang('FilesAttachment').'</div>
+		<div class="formw2">
+				<span id="filepaths">
+				<div id="filepath_1">
+					<input type="file" name="attach_1" id="attach_1"  size="20" style="width:94%;"/>
+				</div></span>
+		</div>
+	</div>';
+	echo '<div class="row">
+		<div class="formw2">
+			<span id="link-more-attach">
+				<a href="javascript://" onclick="return add_image_form()">'.get_lang('AddOneMoreFile').'</a></span>&nbsp;
+					('.sprintf(get_lang('MaximunFileSizeX'),format_file_size(api_get_setting('message_max_upload_filesize'))).')
+			</div>
+		</div>';
+	echo '<div class="row">
+		<div class="label2">
+		</div>
+		<div class="formw2"><button class="save" name="compose"  type="submit" id="btnsubmit">'.get_lang('SendMessage').'</button>
+		</div>
+	</div>';
+	echo '</form></div>';
+}
+function save_ticket(){
+	global $plugin;
+	$category_id	= $_POST['category_id'];
+	$content		= $_POST['content'];
+	if ($_POST['phone']!="")	$content.=	'<p style="color:red">&nbsp;'.get_lang('Phone').': '.$_POST['phone'].'</p>';
+	$course_id		= $_POST['course_id'];
+	$project_id		= $_POST['project_id'];
+	$subject		= $_POST['subject'];
+	$other_area		= (int)$_POST['other_area'];
+	$email			= $_POST['email'];
+	$personal_email	= $_POST['personal_email'];
+	$source 		= $_POST['source_id'];
+	$user_id		= $_POST['user_id_request'];
+	$priority       = $_POST['priority_id'];
+	$status			= $_POST['status_id'];
+	$file_attachments =	$_FILES;
+	if(TicketManager::insert_new_ticket($category_id, $course_id, $project_id, $other_area, $email, $subject, $content,$personal_email, $file_attachments,$source,$priority,$status,$user_id,api_get_user_id())){
+		header('location:'.api_get_path(WEB_PLUGIN_PATH).PLUGIN_NAME.'/s/myticket.php?message=success');
+	}else{
+		Display::display_header(get_lang('ComposeMessage'));
+		Display::display_error_message($plugin->get_lang('ErrorRegisterMessage'));
+	}
+}
+/**
+ * Get the total number of users on the platform
+ * @see SortableTable#get_total_number_of_items()
+ */
+function get_number_of_users() {
+	$user_table = Database :: get_main_table(TABLE_MAIN_USER);
+	$sql = "SELECT COUNT(u.user_id) AS total_number_of_items FROM $user_table u";
+    if ((api_is_platform_admin() || api_is_session_admin()) && api_get_multiple_access_url()) {
+    	$access_url_rel_user_table= Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
+    	$sql.= " INNER JOIN $access_url_rel_user_table url_rel_user ON (u.user_id=url_rel_user.user_id)";
+    }
+	if ( isset ($_GET['keyword'])) {
+		$keyword = Database::escape_string(trim($_GET['keyword']));
+		$sql .= " WHERE (u.firstname LIKE '%".$keyword."%' OR u.lastname LIKE '%".$keyword."%'  OR concat(u.firstname,' ',u.lastname) LIKE '%".$keyword."%'  OR concat(u.lastname,' ',u.firstname) LIKE '%".$keyword."%' OR u.username LIKE '%".$keyword."%' OR u.email LIKE '%".$keyword."%'  OR u.official_code LIKE '%".$keyword."%') ";
+	}
+	$res = Database::query($sql);
+	$obj = Database::fetch_object($res);
+	return $obj->total_number_of_items;
+}
+/**
+ * Get the users to display on the current page (fill the sortable-table)
+ * @param   int     offset of first user to recover
+ * @param   int     Number of users to get
+ * @param   int     Column to sort on
+ * @param   string  Order (ASC,DESC)
+ * @see SortableTable#get_table_data($from)
+ */
+function get_user_data($from, $number_of_items, $column, $direction)
+{
+	$user_table = Database :: get_main_table(TABLE_MAIN_USER);
+	$admin_table = Database :: get_main_table(TABLE_MAIN_ADMIN);
+	$sql = "SELECT
+                 u.user_id				AS col0,
+                 u.official_code		AS col2,
+				 ".(api_is_western_name_order()
+                 ? "u.firstname 			AS col3,
+                 u.lastname 			AS col4,"
+                 : "u.lastname 			AS col3,
+                 u.firstname 			AS col4,")."
+                 u.username				AS col5,
+                 u.email				AS col6,
+                 u.status				AS col7,
+                 u.active				AS col8,
+                 u.user_id				AS col9 ".
+                 ", u.expiration_date      AS exp ".
+            " FROM $user_table u ";
+
+   	if (isset ($_GET['keyword']) ) {
+		$keyword = Database::escape_string(trim($_GET['keyword']));
+		$sql .= " WHERE (u.firstname LIKE '%".$keyword."%' OR u.lastname LIKE '%".$keyword."%' OR concat(u.firstname,' ',u.lastname) LIKE '%".$keyword."%' OR concat(u.lastname,' ',u.firstname) LIKE '%".$keyword."%' OR u.username LIKE '%".$keyword."%'  OR u.official_code LIKE '%".$keyword."%' OR u.email LIKE '%".$keyword."%' )";
+	} 
+    if (!in_array($direction, array('ASC','DESC'))) {
+    	$direction = 'ASC';
+    }
+    $column = intval($column);
+    $from 	= intval($from);
+    $number_of_items = intval($number_of_items);
+
+	$sql .= " ORDER BY col$column $direction ";
+	$sql .= " LIMIT $from,$number_of_items";
+
+	$res = Database::query($sql);
+
+	$users = array ();
+    $t = time();
+	while ($user = Database::fetch_row($res)) {
+		$image_path 	= UserManager::get_user_picture_path_by_id($user[0], 'web', false, true);
+		$user_profile 	= UserManager::get_picture_user($user[0], $image_path['file'], 22, USER_IMAGE_SIZE_SMALL, ' width="22" height="22" ');
+		if (!api_is_anonymous()) {
+			$photo = '<center><a href="'.api_get_path(WEB_PATH).'whoisonline.php?origin=user_list&id='.$user[0].'" title="'.get_lang('Info').'"><img src="'.$user_profile['file'].'" '.$user_profile['style'].' alt="'.api_get_person_name($user[2],$user[3]).'"  title="'.api_get_person_name($user[2], $user[3]).'" /></a></center>';
+		} else {
+			$photo = '<center><img src="'.$user_profile['file'].'" '.$user_profile['style'].' alt="'.api_get_person_name($user[2], $user[3]).'" title="'.api_get_person_name($user[2], $user[3]).'" /></center>';
+		}
+		$user_id= $user[0];
+        $button = '<a href="'.api_get_self().'?user_request='.$user[0].'">'.Display::return_icon('view_more_stats.gif', get_lang('Info')).'</a>';
+        $button= '<a  href="javascript:void(0)" onclick="load_course_list(\'div_'.$user_id.'\','.$user_id.')">
+					<img onclick="load_course_list(\'div_'.$user_id.'\','.$user_id.')"  src="../../../main/img/view_more_stats.gif" title="'.get_lang('Courses').'" alt="'.get_lang('Courses').'"/>
+					</a>&nbsp;&nbsp;';
+        $users[] = array($photo,$user[1],$user[2],$user[3],$user[4],$user[5],$button);        
+	}
+	return $users;
+}
+
+
+
+	if(!isset($_POST['compose'])){
+		Display::display_header(get_lang('ComposeMessage'));
+		echo '
+<div class="actions">
+  <span style="float: right;">&nbsp;</span>
+  <form id="search_simple" name="search_simple" method="get" action="'.api_get_self().'" class="form-search">
+    <fieldset>
+    <span><label for="keyword">'.get_lang('langSearchAUser').': &nbsp;</label><input type="text" name="keyword" size="25"></span>
+    <span><button type="submit" name="submit" class="btn btn">'.get_lang('Search').'</button></span>
+    <div class="clear"></div>
+    </fieldset>
+  </form>
+</div>';
+		if (isset($_GET['keyword'])){
+			$table = new SortableTable('users', 'get_number_of_users', 'get_user_data', (api_is_western_name_order() xor api_sort_by_first_name()) ? 3 : 2);
+			$table->set_header(0, '', false, 'width="18px"');
+			$table->set_header(0, get_lang('Photo'), false);
+			$table->set_header(1, get_lang('OfficialCode'));
+			if (api_is_western_name_order()) {
+				$table->set_header(2, get_lang('FirstName'));
+				$table->set_header(3, get_lang('LastName'));
+			} else {
+				$table->set_header(2, get_lang('LastName'));
+				$table->set_header(3, get_lang('FirstName'));
+			}
+			$table->set_header(4, get_lang('LoginName'));
+			$table->set_header(5, get_lang('Email'));
+			$table->set_header(6, get_lang('Action'));
+			$table->display();
+		}
+		//if(isset($_GET['user_request']))
+			show_form_send_ticket();	
+	}else{
+		save_ticket();
+	}
+
+
+
+Display::display_footer();
+?>

+ 289 - 0
plugin/ticket/s/report.php

@@ -0,0 +1,289 @@
+<?php
+/* 		INIT SECTION	*/
+$language_file= array('messages','userInfo', 'admin','trad4all');
+$cidReset	= true;
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+api_block_anonymous_users();
+require_once api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php';
+require_once api_get_path(LIBRARY_PATH).'group_portal_manager.lib.php';
+
+if(!api_is_allowed_to_edit()){
+	api_not_allowed();
+}
+//$nameTools = api_xml_http_response_encode(get_lang('Soporte Virtual'));
+$this_section = 'Reportes';
+unset($_SESSION['this_section']);
+
+$htmlHeadXtra[]='
+<script language="javascript">
+$(document).ready(function(){
+	 $( "#keyword_start_date_start" ).datepicker({ dateFormat: '."'yy-mm-dd'".' });
+   	$( "#keyword_start_date_end" ).datepicker({ dateFormat: '."'yy-mm-dd'".' });
+});
+function validate(){
+  if( $("#keyword_start_date_start").val() != "" &&  $("#keyword_start_date_end").val() != ""){
+   datestart = $("#keyword_start_date_start").val();
+   dateend = $("#keyword_start_date_end").val();
+   dif = $.datepicker.parseDate("dd/mm/yy", datestart) -  $.datepicker.parseDate("dd/mm/yy", dateend);
+   if(dif > 0){
+	alert("La fecha final no puede ser mayor a la fecha inicial");
+   			return false;
+   			}
+  }
+}
+function load_course_list (div_course,my_user_id) {
+	 $.ajax({
+		contentType: "application/x-www-form-urlencoded",
+		type: "GET",
+		url: "course_user_list.php",
+		data: "user_id="+my_user_id,
+		success: function(datos) {
+			$("div#user_request").html(datos);
+			$("#btnsubmit").attr("disabled", false);
+		}
+	});
+}
+</script>
+
+<style>
+div.row div.label2 {
+	float:left;
+	width:10%;
+}
+div.row div.formw2 {
+    width:90%;
+	float:left
+}
+div.formulario {
+    width: 70%;
+	float: center;
+	margin-left: 15%;
+	
+}
+
+</style>';
+$types = TicketManager::get_all_tickets_categories();
+$htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
+$htmlHeadXtra[] = '<link  href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
+$tools = array();
+$tools['todas']= array('id'=>'','name'=>get_lang('Todas'));
+$tools['announcement']= array('id'=>'announcement','name'=>get_lang('Announcement'));
+// $tools[]= array('id'=>'assignment','name'=>get_lang('Assignment'));
+$tools['calendar_event']= array('id'=>'calendar_event','name'=>get_lang('Calendar_event'));
+$tools['chat']= array('id'=>'chat','name'=>get_lang('Chat'));
+$tools['conference']= array('id'=>'conference','name'=>get_lang('Conference'));
+$tools['course_description']= array('id'=>'course_description','name'=>get_lang('Course_description'));
+$tools['document']= array('id'=>'document','name'=>get_lang('Document'));
+$tools['dropbox']= array('id'=>'dropbox','name'=>get_lang('Dropbox'));
+$tools['group']= array('id'=>'group','name'=>get_lang('Group'));
+$tools['learnpath']= array('id'=>'learnpath','name'=>get_lang('Learnpath'));
+$tools['link']= array('id'=>'link','name'=>get_lang('Link'));
+$tools['quiz']= array('id'=>'quiz','name'=>get_lang('Quiz'));
+$tools['student_publication']= array('id'=>'student_publication','name'=>get_lang('Student_publication'));
+$tools['user']= array('id'=>'user','name'=>get_lang('User'));
+$tools['forum']= array('id'=>'forum','name'=>get_lang('Forum'));
+
+function js_str($s) {
+	return '"'.addcslashes($s, "\0..\37\"\\").'"';
+}
+
+function show_form(){
+	global $types; 
+	global $tools;
+	echo '<div class="formulario">';
+	echo '<form enctype="multipart/form-data" action="'.api_get_self().'" method="post" name="send_ticket" id="send_ticket"
+ 	onsubmit="return validate()" style="width:100%">';
+	
+	$courses_list = CourseManager::get_courses_list_by_user_id($user_id,false,true);
+	 $select_course = '<div id="user_request" >
+	 </div>';
+	echo $select_course;
+	//select status
+	$select_tool = '<div class="row"  >
+	<div class="label2"  >Herramienta:</div>
+	<div class="formw2">';
+	$select_tool .= '<select style="width: 95%; " name = "tool" id="tool" >';
+	$status = TicketManager::get_all_tickets_status();
+	foreach ($tools as $tool) {
+			$select_tool .=  "<option value = '".$tool['id']."' selected >".$tool['name']."</option>";
+	}
+	$select_tool .= "</select>";
+	$select_tool .= '</div></div>';
+	echo $select_tool;
+	echo '<div class="row">
+			<div class="label2">Desde:</div>
+			<div class="formw2"><input id="keyword_start_date_start" name="keyword_start_date_start" type="text"></div>
+		  </div>
+			<div class="row">
+			<div class="label2">Hasta</div>
+			<div class="formw2"><input id="keyword_start_date_end" name="keyword_start_date_end" type="text"></div>
+			</div>';
+	echo '</div>';
+	echo '<div class="row">
+		<div class="label2">
+		</div>
+		<div class="formw2">	
+			<button class="save" name="report" type="submit" id="btnsubmit" disabled="disabled">Generar Reporte</button>
+		</div>
+	</div>';
+	
+}
+/**
+ * Get the total number of users on the platform
+ * @see SortableTable#get_total_number_of_items()
+ */
+function get_number_of_users() {
+	$user_table = Database :: get_main_table(TABLE_MAIN_USER);
+	$sql = "SELECT COUNT(u.user_id) AS total_number_of_items FROM $user_table u";
+    if ((api_is_platform_admin() || api_is_session_admin()) && api_get_multiple_access_url()) {
+    	$access_url_rel_user_table= Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
+    	$sql.= " INNER JOIN $access_url_rel_user_table url_rel_user ON (u.user_id=url_rel_user.user_id)";
+    }
+	if ( isset ($_GET['keyword'])) {
+		$keyword = Database::escape_string(trim($_GET['keyword']));
+		$sql .= " WHERE (u.firstname LIKE '%".$keyword."%' OR u.lastname LIKE '%".$keyword."%'  OR concat(u.firstname,' ',u.lastname) LIKE '%".$keyword."%'  OR concat(u.lastname,' ',u.firstname) LIKE '%".$keyword."%' OR u.username LIKE '%".$keyword."%' OR u.email LIKE '%".$keyword."%'  OR u.official_code LIKE '%".$keyword."%') ";
+	}
+	$res = Database::query($sql);
+	$obj = Database::fetch_object($res);
+	return $obj->total_number_of_items;
+}
+/**
+ * Get the users to display on the current page (fill the sortable-table)
+ * @param   int     offset of first user to recover
+ * @param   int     Number of users to get
+ * @param   int     Column to sort on
+ * @param   string  Order (ASC,DESC)
+ * @see SortableTable#get_table_data($from)
+ */
+function get_user_data($from, $number_of_items, $column, $direction)
+{
+	$user_table = Database :: get_main_table(TABLE_MAIN_USER);
+	$admin_table = Database :: get_main_table(TABLE_MAIN_ADMIN);
+	$sql = "SELECT
+                 u.user_id				AS col0,
+                 u.official_code		AS col2,
+				 ".(api_is_western_name_order()
+                 ? "u.firstname 			AS col3,
+                 u.lastname 			AS col4,"
+                 : "u.lastname 			AS col3,
+                 u.firstname 			AS col4,")."
+                 u.username				AS col5,
+                 u.email				AS col6,
+                 u.status				AS col7,
+                 u.active				AS col8,
+                 u.user_id				AS col9 ".
+                 ", u.expiration_date      AS exp ".
+            " FROM $user_table u ";
+
+   	if (isset ($_GET['keyword']) ) {
+		$keyword = Database::escape_string(trim($_GET['keyword']));
+		$sql .= " WHERE (u.firstname LIKE '%".$keyword."%' OR u.lastname LIKE '%".$keyword."%' OR concat(u.firstname,' ',u.lastname) LIKE '%".$keyword."%' OR concat(u.lastname,' ',u.firstname) LIKE '%".$keyword."%' OR u.username LIKE '%".$keyword."%'  OR u.official_code LIKE '%".$keyword."%' OR u.email LIKE '%".$keyword."%' )";
+	} 
+    if (!in_array($direction, array('ASC','DESC'))) {
+    	$direction = 'ASC';
+    }
+    $column = intval($column);
+    $from 	= intval($from);
+    $number_of_items = intval($number_of_items);
+
+	$sql .= " ORDER BY col$column $direction ";
+	$sql .= " LIMIT $from,$number_of_items";
+
+	$res = Database::query($sql);
+
+	$users = array ();
+    $t = time();
+	while ($user = Database::fetch_row($res)) {
+		$image_path 	= UserManager::get_user_picture_path_by_id($user[0], 'web', false, true);
+		$user_profile 	= UserManager::get_picture_user($user[0], $image_path['file'], 22, USER_IMAGE_SIZE_SMALL, ' width="22" height="22" ');
+		if (!api_is_anonymous()) {
+			$photo = '<center><a href="'.api_get_path(WEB_PATH).'whoisonline.php?origin=user_list&id='.$user[0].'" title="'.get_lang('Info').'"><img src="'.$user_profile['file'].'" '.$user_profile['style'].' alt="'.api_get_person_name($user[2],$user[3]).'"  title="'.api_get_person_name($user[2], $user[3]).'" /></a></center>';
+		} else {
+			$photo = '<center><img src="'.$user_profile['file'].'" '.$user_profile['style'].' alt="'.api_get_person_name($user[2], $user[3]).'" title="'.api_get_person_name($user[2], $user[3]).'" /></center>';
+		}
+		$user_id= $user[0];
+        $button = '<a href="'.api_get_self().'?user_request='.$user[0].'">'.Display::return_icon('view_more_stats.gif', get_lang('Info')).'</a>';
+        $button= '<a  href="javascript:void(0)" onclick="load_course_list(\'div_'.$user_id.'\','.$user_id.')">
+					<img onclick="load_course_list(\'div_'.$user_id.'\','.$user_id.')"  src="../../../main/img/view_more_stats.gif" title="'.get_lang('Courses').'" alt="'.get_lang('Courses').'"/>
+					</a>&nbsp;&nbsp;';
+        $users[] = array($photo,$user[1],$user[2],$user[3],$user[4],$user[5],$button);        
+	}
+	return $users;
+}
+
+
+
+Display::display_header('Reportes');
+		echo '<div class="actions">
+		<form action="'.api_get_self().'" method="get" name="search_simple" id="search_simple">
+			<input name="user_id_request" id="user_id_request" type="hidden" value="">
+			<span><label for="keyword">B&uacute;squeda del usuario: </label><input size="25" name="keyword" type="text" id="keyword"></span>
+			<span><button class="search" name="submit" type="submit">Buscar</button></span>
+			<div class="clear">&nbsp;</div>
+		</form></div>';
+		if (isset($_GET['keyword'])){
+			$table = new SortableTable('users', 'get_number_of_users', 'get_user_data', (api_is_western_name_order() xor api_sort_by_first_name()) ? 3 : 2);
+			$table->set_header(0, '', false, 'width="18px"');
+			$table->set_header(0, get_lang('Photo'), false);
+			$table->set_header(1, get_lang('OfficialCode'));
+			if (api_is_western_name_order()) {
+				$table->set_header(2, get_lang('FirstName'));
+				$table->set_header(3, get_lang('LastName'));
+			} else {
+				$table->set_header(2, get_lang('LastName'));
+				$table->set_header(3, get_lang('FirstName'));
+			}
+			$table->set_header(4, get_lang('LoginName'));
+			$table->set_header(5, get_lang('Email'));
+			$table->set_header(6, get_lang('Action'));
+			$table->display();
+		}
+		//if(isset($_GET['user_request']))
+				
+	if(isset($_POST['report'])){
+		$course_id = $_POST['course_id'];
+		$tool = $_POST['tool'];
+		$course_info = api_get_course_info_by_id($course_id);
+		$user_id =  $_POST['user_id_request'];
+		$sql ="SELECT  u.username , CONCAT(u.lastname, ' ', u.firstname) AS fullname, DATE_SUB(access.access_date,INTERVAL 5 HOUR) AS  access_date, c.title AS curso, access_tool AS herramienta 
+				FROM  ".Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ACCESS)." access 
+				LEFT JOIN  ".Database::get_main_table(TABLE_MAIN_USER)." u ON access.access_user_id = u.user_id 
+				LEFT JOIN  ".Database::get_main_table(TABLE_MAIN_COURSE)." c ON access.access_cours_code = c.CODE 
+				WHERE access.access_cours_code = '".$course_info['code']."' AND u.user_id = '$user_id' ";
+		if($tool!= '') $sql.="AND access.access_tool = '$tool' ";
+		$start_date = $_POST['keyword_start_date_start'];
+		$end_date 	= $_POST['keyword_start_date_end'];
+		if ($start_date != '' || $end_date != ''){
+			$sql .= " HAVING ";
+			if ($start_date != '') $sql .=  "  access_date >= '$start_date'   ";
+			if ($end_date != '') {
+				$sql = ($start_date == '')?$sql:($sql." AND ");
+				$sql .=  "  access_date <= '$end_date'   ";
+			}
+				
+		}
+		$result = Database::query($sql);
+		$table_result = new SortableTable();
+		$table_result->set_header(0, get_lang('User'), false);
+		$table_result->set_header(1, get_lang('Fullname'), false);
+		$table_result->set_header(2, get_lang('Fecha'), false);
+		$table_result->set_header(3, get_lang('curso'), false);
+		$table_result->set_header(4, get_lang('Herramienta'), false);
+		while ($row = Database::fetch_assoc($result)){
+			$row = array(0 =>$row['username'],1 =>$row['fullname'],2 => $row['access_date'],3 =>$row['curso'],4 =>get_lang($tools[$row['herramienta']]['name']));
+			$table_result->addRow($row);
+		}
+		$table_result->display();
+		
+		
+	}else{
+		show_form();
+	}
+
+
+
+Display::display_footer();
+
+?>

+ 246 - 0
plugin/ticket/s/send_ticket.php

@@ -0,0 +1,246 @@
+<?php
+/*    INIT SECTION   */
+$language_file = array('messages','userInfo', 'admin');
+$cidReset = true;
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+api_block_anonymous_users();
+require_once api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php';
+require_once api_get_path(LIBRARY_PATH).'group_portal_manager.lib.php';
+
+$htmlHeadXtra[]='
+<script>
+$(document).ready(function(){
+	if(document.getElementById("divEmail")){
+		document.getElementById("divEmail").style.display="none";
+	}
+});
+function changeType() {
+var selected = document.getElementById("category_id").selectedIndex;
+var id = document.getElementById("category_id").options[selected].value  ;
+	document.getElementById("project_id").value= projects[id];
+	document.getElementById("other_area").value= other_area[id];
+	document.getElementById("email").value= email[id];
+	document.getElementById("divEmail").style.display="none";
+	if(parseInt(course_required[id]) == 0){
+		document.getElementById("divCourse").style.display="none";		
+		if( id != "CUR"){
+			document.getElementById("divEmail").style.display="";
+			document.getElementById("personal_email").required="required";	
+		}			
+		document.getElementById("course_id").disabled=true;	
+		document.getElementById("course_id").value=0;			
+	}else{	
+		document.getElementById("divCourse").style.display = "";
+		document.getElementById("course_id").disabled=false;
+		document.getElementById("course_id").value=0;
+		document.getElementById("personal_email").value="";
+	}
+}
+
+function validate() {
+	var re  = /^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/; 
+	fckEditor1val = FCKeditorAPI.__Instances["content"].GetHTML();
+	document.getElementById("content").value= fckEditor1val;
+	var selected = document.getElementById("category_id").selectedIndex;
+	var id = document.getElementById("category_id").options[selected].value;
+	if( id == 0){
+		alert("'.$plugin->get_lang("ValidType").'");
+		return false;
+	}else if(document.getElementById("subject").value == ""){
+		alert("'.$plugin->get_lang("ValidSubject").'");
+		return false;
+	}else if(parseInt(course_required[id]) == 1 && document.getElementById("course_id").value == 0){
+		alert("'.$plugin->get_lang("ValidCourse").'");
+		return false;
+	}else if(id !="CUR" && parseInt(course_required[id]) != 1  && !re.test(document.getElementById("personal_email").value)){
+		alert("'.$plugin->get_lang("ValidEmail").'");
+		return false;
+	}else if(fckEditor1val ==""){
+		alert("'.$plugin->get_lang("ValidMessage").'");
+		return false;
+	}
+}
+
+var counter_image = 1;
+function remove_image_form(id_elem1) {
+	var elem1 = document.getElementById(id_elem1);
+	elem1.parentNode.removeChild(elem1);
+	counter_image = counter_image - 1;
+}
+function add_image_form() {
+	// Multiple filepaths for image form
+	var filepaths = document.getElementById("filepaths");
+	if (document.getElementById("filepath_"+counter_image)) {
+		counter_image = counter_image + 1;
+	}  else {
+		counter_image = counter_image;
+	}
+	var elem1 = document.createElement("div");
+	elem1.setAttribute("id","filepath_"+counter_image);
+	filepaths.appendChild(elem1);
+	id_elem1 = "filepath_"+counter_image;
+	id_elem1 = "\'"+id_elem1+"\'";
+	document.getElementById("filepath_"+counter_image).innerHTML = "<input type=\"file\" name=\"attach_"+counter_image+"\"  size=\"20\" />&nbsp;<a href=\"javascript:remove_image_form("+id_elem1+")\"><img src=\"'.api_get_path(WEB_CODE_PATH).'img/delete.gif\"></a>";
+	//document.getElementById("filepath_"+counter_image).innerHTML = "<input type=\"file\" name=\"attach_"+counter_image+"\"  size=\"20\" />&nbsp;<input type=\"text\" name=\"legend[]\" size=\"20\" />";
+	if (filepaths.childNodes.length == 6) {
+		var link_attach = document.getElementById("link-more-attach");
+		if (link_attach) {
+			link_attach.innerHTML="";
+		}
+	}
+}
+function show_question(questionid){
+	if(document.getElementById("C"+questionid)){
+		if(document.getElementById("A"+questionid).style.display == "none"){
+			document.getElementById("A"+questionid).style.display = ""; 
+		}
+		else if(document.getElementById("A"+questionid).style.display == ""){
+			document.getElementById("A"+questionid).style.display = "none"; 
+		}
+	}	
+}
+</script>
+
+<style>
+div.row div.label2 {
+	float:left;
+	width:10%;
+}
+div.row div.formw2 {
+    width:90%;
+	float:left
+}
+div.divTicket {
+    width: 70%;
+	float: center;
+	margin-left: 15%;
+	
+}
+</style>';
+$types = TicketManager::get_all_tickets_categories();
+$htmlHeadXtra[] = '<script language="javascript">
+		var projects = '.js_array($types,'projects','project_id'). '
+		var course_required = '.js_array($types,'course_required','course_required').'
+		var other_area = '.js_array($types,'other_area','other_area').'
+		var email = '.js_array($types,'email','email').'
+		document.getElementById("divCourse").style.display="none";	
+		 </script>';
+$htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
+$htmlHeadXtra[] = '<link  href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
+
+function js_str($s) {
+	return '"'.addcslashes($s, "\0..\37\"\\").'"';
+}
+
+function js_array($array,$name,$key) {
+	$temp=array();
+	$return = "new Array(); ";
+	foreach ($array as $value){
+		$return .= $name."['".$value['category_id']."'] ='".$value[$key]."'; ";
+	}
+	return $return;
+}
+
+function show_form_send_ticket(){
+	global $types, $plugin;
+	$courses_list = CourseManager::get_courses_list_by_user_id(api_get_user_id(),false,true);
+	echo '<div class="divTicket">';
+	echo '<form enctype="multipart/form-data" action="'.api_get_self().'" method="post" name="send_ticket" id="send_ticket"
+ 	onsubmit="return validate()" style="width:100%">';
+	$select_types = '<div class="row">
+	<div class="label2">'.get_lang('Category').': </div>
+       <div class="formw2">';
+	$select_types .= '<select style="width: 95%; "   name = "category_id" id="category_id" onChange="changeType();">';
+	$select_types .= '<option value="0">---'.get_lang('Select').'---</option>';
+	foreach ($types as $type) {
+		$select_types.= "<option value = '".$type['category_id']."'>".$type['name'].":  <br/>".$type['description']."</option>";
+	}
+	$select_types .= "</select>";
+	$select_types .= '</div></div>';
+	echo $select_types;
+	$select_course = '<div class="row" id="divCourse" >
+	<div class="label2"  >'.get_lang('Course').':</div>
+            <div class="formw2">';
+	$select_course .= '<select  class="chzn-select" name = "course_id" id="course_id"  style="width: 40%; display:none;">';
+	$select_course .= '<option value="0">---'.get_lang('Select').'---</option>';
+	foreach ($courses_list as $course) {
+		$select_course.= "<option value = '".$course['course_id']."'>".$course['title']."</option>";
+	}
+	$select_course .= "</select>";
+	$select_course .= '</div></div>';
+	echo $select_course;
+	echo '<div class="row" ><div class ="label2">'.get_lang('Subject').':</div>
+       		<div class="formw2"><input type = "text" id ="subject" name="subject" value="" required ="" style="width:94%"/></div>
+		  </div>';
+	echo '<div class="row" id="divEmail" ><div class ="label2">'.$plugin->get_lang('PersonalEmail').':</div>
+       		<div class="formw2"><input type = "email" id ="personal_email" name="personal_email" value=""  style="width:94%"/></div>
+		  </div>';
+	echo '<input name="project_id" id="project_id" type="hidden" value="">';
+	echo '<input name="other_area" id="other_area" type="hidden" value="">';
+	echo '<input name="email" id="email" type="hidden" value="">';
+	echo '<div class="row">
+		<div class="label2">'.get_lang('Message').'</div>
+		<div class="formw2">
+			<input type="hidden" id="content" name="content" value="" style="display:none">
+		<input type="hidden" id="content___Config" value="ToolbarSet=Messages&amp;Width=95%25&amp;Height=250&amp;ToolbarSets={ %22Messages%22: [  [ %22Bold%22,%22Italic%22,%22-%22,%22InsertOrderedList%22,%22InsertUnorderedList%22,%22Link%22,%22RemoveLink%22 ] ], %22MessagesMaximized%22: [  ] }&amp;LoadPlugin=[%22customizations%22]&amp;EditorAreaStyles=body { background: #ffffff; }&amp;ToolbarStartExpanded=false&amp;CustomConfigurationsPath=/main/inc/lib/fckeditor/myconfig.js&amp;EditorAreaCSS=/main/css/chamilo/default.css&amp;ToolbarComboPreviewCSS=/main/css/chamilo/default.css&amp;DefaultLanguage=es&amp;ContentLangDirection=ltr&amp;AdvancedFileManager=true&amp;BaseHref='.api_get_path(WEB_PLUGIN_PATH).PLUGIN_NAME.'/s/&amp;&amp;UserIsCourseAdmin=true&amp;UserIsPlatformAdmin=true" style="display:none">
+		<iframe id="content___Frame" src="/main/inc/lib/fckeditor/editor/fckeditor.html?InstanceName=content&amp;Toolbar=Messages" width="95%" height="250" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border: 0px; background-color: transparent; background-image: none; width: 95%; height: 250px;">
+		</iframe>
+		</div>
+	</div>';
+	echo '<div class="row" ><div class ="label2">'.get_lang('Phone').' ('.$plugin->get_lang('Optional').'):</div>
+       		<div class="formw2"><input type = "text" id ="phone" name="phone" value="" onkeyup="valid(this,'."'allowspace'".')" onblur="valid(this,'."'allowspace'".')" style="width:94%"/></div>
+		</div>';
+	echo '<div class="row">
+		<div class="label2">'.get_lang('FilesAttachment').'</div>
+		<div class="formw2">
+				<span id="filepaths">
+				<div id="filepath_1">
+					<input type="file" name="attach_1" id="attach_1"  size="20" style="width:94%;"/>
+				</div></span>
+		</div>
+	</div>';
+	echo '<div class="row">
+		<div class="formw2">
+			<span id="link-more-attach">
+				<a href="javascript://" onclick="return add_image_form()">'.get_lang('AddOneMoreFile').'</a></span>&nbsp;
+					('.sprintf(get_lang('MaximunFileSizeX'),format_file_size(api_get_setting('message_max_upload_filesize'))).')
+			</div>
+		</div>';
+	echo '<div class="row">
+		<div class="label2">
+		</div>
+		<div class="formw2"><button class="save" name="compose"  type="submit" id="btnsubmit">'.get_lang('SendMessage').'</button>
+		</div>
+	</div>';
+	echo '</form></div>';
+}
+
+function save_ticket(){
+	$category_id	=	$_POST['category_id'];
+	$content		=	$_POST['content'];
+	if ($_POST['phone']!="")	$content.=	'<p style="color:red">&nbsp;'.get_lang('Phone').': '.$_POST['phone'].'</p>';
+	$course_id		=	$_POST['course_id'];
+	$project_id		=	$_POST['project_id'];
+	$subject		=	$_POST['subject'];
+	$other_area		=	(int)$_POST['other_area'];
+	$email			=	$_POST['email'];
+	$personal_email	= $_POST['personal_email'];
+	$file_attachments =	$_FILES;
+	if(TicketManager::insert_new_ticket($category_id, $course_id, $project_id, $other_area, $email, $subject, $content,$personal_email, $file_attachments)){
+		header('location:'.api_get_path(WEB_PLUGIN_PATH).PLUGIN_NAME.'/s/myticket.php?message=success');
+	}else{
+		Display::display_header(get_lang('ComposeMessage'));
+		Display::display_error_message($plugin->get_lang('ErrorRegisterMessage'));
+	}
+}
+
+if(!isset($_POST['compose'])){
+	Display::display_header(get_lang('ComposeMessage'));
+	show_form_send_ticket();
+}else{
+	save_ticket();
+}
+
+Display::display_footer();

+ 15 - 0
plugin/ticket/s/test.html

@@ -0,0 +1,15 @@
+<div class="actions">
+  <span style="float: right;">
+    <a href="http://chamilo196/main/admin/user_add.php"><img title="Añadir usuarios" alt="Añadir usuarios" src="http://chamilo196/main/img/icons/32/new_user.png"></a>
+  </span>
+  <form id="search_simple" name="search_simple" method="get" action="/main/admin/user_list.php" class="form-search">
+    <fieldset>
+    <span><input type="text" name="keyword" size="25"></span>
+    <span><button type="submit" name="submit" class="btn btn">Buscar</button></span>
+    <span><a onclick="display_advanced_search_form();" class="advanced_parameters" href="javascript://">
+      <span id="img_plus_and_minus">&nbsp;<img title="Mostrar" alt="Mostrar" src="http://chamilo196/main/img/div_show.gif" style="vertical-align: middle">&nbsp;Búsqueda avanzada</span></a>
+    </span>
+    <div class="clear"></div>
+    </fieldset>
+  </form>
+</div>

+ 673 - 0
plugin/ticket/s/ticket.class.php

@@ -0,0 +1,673 @@
+<?php
+
+class TicketManager {
+	function TicketManager(){		
+	}
+	public static function get_all_tickets_categories(){
+		$table_support_category = Database::get_main_table(TABLE_SUPPORT_CATEGORY);
+		$table_support_project = Database::get_main_table(TABLE_SUPPORT_PROJECT);
+		$sql = "SELECT category.*, project.other_area , project.email FROM ".$table_support_category."  category,".$table_support_project." project WHERE project.project_id = category.project_id ORDER BY category.total_tickets DESC;";
+		$result = Database::query($sql);
+		$types = array();
+		while  ($row = Database::fetch_assoc($result)) {
+			$types[]=$row;
+		}
+		return $types;
+	}
+	public static function get_all_tickets_status(){
+		$table_support_status = Database::get_main_table(TABLE_SUPPORT_STATUS);
+		$sql = "SELECT * FROM ".$table_support_status;
+		$result = Database::query($sql);
+		$types = array();
+		while  ($row = Database::fetch_assoc($result)) {
+			$types[]=$row;
+		}
+		return $types;
+	}
+	public static function insert_new_ticket($category_id, $course_id,$project_id,$other_area, $email,$subject, $content,$personalemail="",$file_attachments,$source='VRT',$priority='NRM',$status='',$request_user ='',$assigned_user=0){
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$table_support_category = Database::get_main_table(TABLE_SUPPORT_CATEGORY);
+		$now = api_get_utc_datetime();
+		$user_id = api_get_user_id();
+		if($status == ''){
+			$status = NEWTCK;
+			if($other_area > 0){
+				$status = REENVIADO;
+			}
+		}
+
+		if($request_user == ''&& $source == 'VRT'){ 
+			$request_user = $user_id;
+		}
+		$course_id = intval($course_id);
+		$sql_insert_ticket= "INSERT INTO ".$table_support_tickets." (project_id,category_id,priority_id,course_id, request_user, personal_email ,status_id, start_date,sys_insert_user_id,sys_insert_datetime,sys_lastedit_user_id,sys_lastedit_datetime,source)
+		VALUES ('$project_id','$category_id','$priority','$course_id','$request_user','$personalemail','$status','".$now."',$user_id,'".$now."','$user_id','".$now."','$source')";
+		$result = Database::query($sql_insert_ticket);
+		$ticket_id = Database::insert_id();
+		if ( $assigned_user!= 0){
+			self::assign_ticket_user($ticket_id, $assigned_user);
+		}
+		if($ticket_id != 0){
+			$ticket_code ="A".str_pad((int) $ticket_id,11,"0",STR_PAD_LEFT);
+			$sql_update_code = "UPDATE ".$table_support_tickets." SET ticket_code = '$ticket_code' WHERE ticket_id = '$ticket_id'";
+			Database::query($sql_update_code);
+			$data_files = array();
+			$sql_update_total = "UPDATE ".$table_support_category." SET total_tickets = total_tickets +1 WHERE category_id = '$category_id';";
+			Database::query($sql_update_total);
+			if(self::insert_message($ticket_id, $subject, $content,$file_attachments, $request_user)){
+				global $data_files;
+				if($other_area){
+					$user = UserManager::get_user_info_by_id($request_user);
+					$mensaje_helpdesk = '<table>
+											<tr>
+												<td width="100px"><b>Cliente:</b></td>
+												<td width="400px">'.$user['firstname'].' '.$user['lastname'].'</td>
+											</tr>
+											<tr>
+												<td width="100px"><b>Usuario:</b></td>
+												<td width="400px">'.$user['username'].'</td>
+											</tr>
+											<tr>
+												<td width="100px"><b>Fecha:</b></td>
+												<td width="400px">'.api_convert_and_format_date($now, DATE_TIME_FORMAT_LONG).'</td>
+											</tr>
+											<tr>
+												<td width="100px"><b>Asunto:</b></td>
+												<td width="400px">'.$subject.'</td>
+											</tr>
+											<tr>
+												<td width="100px"><b>Descripci&oacute;n:</b></td>
+												<td width="400px">'.$content.'</td>
+											</tr>
+										</table>';
+					api_mail_html('Soporte virtual', $email, "[SOPORTE] Incidente Reenviado de Soporte Virtual", $mensaje_helpdesk,$user['firstname'].' '.$user['lastname'], $personalemail, array('cc'=>'soportevirtual@usil.edu.pe'), $data_files);
+					$mensaje_alumno ='<p>Su consulta fue reenviada al area responsable : <a href="mailto:'.$email.'">'.$email.'</a></p>';
+					$mensaje_alumno .='<p>La respuesta a su consulta ser&aacute; enviada al correo  : <a href="#">'.$personalemail.'</a></p>';
+					self::insert_message($ticket_id, "Mensaje Reenviado", $mensaje_alumno, null, 1);
+				}
+				return true;
+			}else{
+				return false;
+			}
+		}else{
+			return false;
+		}
+	}
+	public static function insert_message($ticket_id,$subject,$content,$file_attachments,$user_id,$status='NOL',$envioconfirmacion=false){
+		global $data_files;
+		$table_support_messages = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$table_support_message_attachments = Database::get_main_table(TABLE_SUPPORT_MESSAGE_ATTACHMENTS);
+		if ($envioconfirmacion){
+			$formulario = '<form action="ticket_details.php?ticket_id='.$ticket_id.'" id="confirmticket" method="POST" >
+							<p>Esta respuesta le result&oacute; satisfactoria</p>
+							<input id="respuestasi" type="submit" value="si" name="respuesta" />
+							<input id="respuestano" type="submit" value="no" name="respuesta" />
+						   </form>';
+			$content.=$formulario;
+			Database::query("UPDATE $table_support_tickets SET status_id='XCF' WHERE ticket_id = '$ticket_id'");
+		}
+		$sql_message_id = "SELECT COUNT(*) as total_messages FROM ".$table_support_messages." WHERE ticket_id ='$ticket_id'";
+		$result = Database::query($sql_message_id);
+		$obj = Database::fetch_object($result);
+		$message_id = $obj->total_messages+1;
+		$now = api_get_utc_datetime();
+		$sql_insert_message = "INSERT INTO ".$table_support_messages." (ticket_id,message_id,subject, message,ip_address,sys_insert_user_id,sys_insert_datetime,sys_lastedit_user_id,sys_lastedit_datetime,status)
+		VALUES ('$ticket_id','$message_id','$subject','$content','".$_SERVER['REMOTE_ADDR']."','$user_id','".$now."','$user_id','".$now."','$status');";
+		Database::query($sql_insert_message);
+		$sql_update_total_message ="UPDATE ".$table_support_tickets." SET sys_lastedit_user_id ='$user_id' , sys_lastedit_datetime ='".$now."' , total_messages = ("."SELECT COUNT(*) as total_messages FROM ".$table_support_messages." WHERE ticket_id ='$ticket_id'".") WHERE ticket_id ='$ticket_id' ";
+		Database::query($sql_update_total_message);
+		$sql_message_att_id = "SELECT COUNT(*) as total_attach FROM ".$table_support_message_attachments." WHERE ticket_id ='$ticket_id' AND message_id = '$message_id'";
+		$result = Database::query($sql_message_att_id);
+		$obj = Database::fetch_object($result);
+		$message_attch_id = $obj->total_attach+1;
+		if (is_array($file_attachments)) {
+			foreach ($file_attachments as $file_attach) {				
+				if ($file_attach['error'] == 0) {
+					$data_files[] = self::save_message_attachment_file($file_attach,$ticket_id,$message_id,$message_attch_id);
+					$message_attch_id++;
+				}else{
+					if($file_attach['error']!=UPLOAD_ERR_NO_FILE )return false;
+				}
+			}
+		}
+		return true;
+		
+		
+	}
+	public static function save_message_attachment_file($file_attach,$ticket_id,$message_id,$message_attch_id) {
+		$now = api_get_ut;
+		$user_id = api_get_user_id();
+		$new_file_name = add_ext_on_mime(stripslashes($file_attach['name']), $file_attach['type']);
+		$file_name =$file_attach['name'];
+		$table_support_message_attachments = Database::get_main_table(TABLE_SUPPORT_MESSAGE_ATTACHMENTS);
+		if (!filter_extension($new_file_name))  {
+			Display :: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
+		} else {
+			$new_file_name = uniqid('');
+			$path_attachment = api_get_path(SYS_PATH);
+			$path_message_attach =$path_attachment.'tck_messageattch/';
+			if (!file_exists($path_message_attach)) {
+				@mkdir($path_message_attach, api_get_permissions_for_new_directories(), true);
+			}
+			$new_path=$path_message_attach.$new_file_name;
+			if (is_uploaded_file($file_attach['tmp_name'])) {
+				$result= @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);
+			$sql="INSERT INTO ".$table_support_message_attachments."(filename, path,ticket_id,message_id,message_attch_id,size,sys_insert_user_id,sys_insert_datetime,sys_lastedit_user_id,sys_lastedit_datetime)
+			VALUES ( '$safe_file_name',  '$safe_new_file_name' , '$ticket_id','$message_id', '$message_attch_id','".$file_attach['size']."','$user_id','".$now."','$user_id','".$now."' )";
+			$result=Database::query($sql);
+			return array('path' => $path_message_attach.$safe_new_file_name,'filename' => $safe_file_name);
+		}
+	}
+	public static function get_tickets_by_user_id($from, $number_of_items, $column, $direction ,$user_id=null){
+		$table_support_category = Database::get_main_table(TABLE_SUPPORT_CATEGORY);
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$table_support_priority = Database::get_main_table(TABLE_SUPPORT_PRIORITY);
+		$table_support_status = Database::get_main_table(TABLE_SUPPORT_STATUS);
+		$table_support_messages = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+		$table_main_user = Database::get_main_table(TABLE_MAIN_USER);
+		$table_main_admin = Database::get_main_table(TABLE_MAIN_ADMIN);
+		if(is_null($direction)) $direction ="DESC";
+		if(is_null($user_id) || $user_id==0){
+			$user_id = api_get_user_id();
+		}
+		
+		$isAdmin = UserManager::is_admin($user_id);
+		$sql = "SELECT ticket.*,  ticket.ticket_id AS col0,ticket.start_date AS col1, ticket.sys_lastedit_datetime AS col2 ,cat.name AS col3,user.username AS col4, priority.priority AS col5 ,
+				priority.priority  AS col6, status.name AS col7 , ticket.total_messages AS col8, msg.message AS col9, ticket.request_user AS user_id , ticket.assigned_last_user AS responsable 
+				FROM ".$table_support_tickets." ticket ,".$table_support_category." cat , ".$table_support_priority ." priority, ".$table_support_status ." status , ".Database::get_main_table(TABLE_MAIN_USER)." user, tck_message msg 
+				WHERE cat.category_id = ticket.category_id AND ticket.priority_id = priority.priority_id AND ticket.status_id = status.status_id  AND user.user_id = ticket.request_user
+				AND ticket.ticket_id= msg.ticket_id AND message_id=1 ";
+		if(!$isAdmin){
+			$sql.=" AND request_user = '$user_id' ";
+		}
+		$keyword_unread = Database::escape_string(trim($_GET['keyword_unread']));
+		//Search simple
+		if(isset($_GET['submit_simple'])){
+			if($_GET['keyword']!=''){
+				$keyword = Database::escape_string(trim($_GET['keyword']));
+				$sql.=" AND (ticket.ticket_code = '".$keyword."' OR ticket.ticket_id = '".$keyword."' OR user.firstname LIKE '%".$keyword."%' OR user.lastname LIKE '%".$keyword."%'  OR concat(user.firstname,' ',user.lastname) LIKE '%".$keyword."%'  OR concat(user.lastname,' ',user.firstname) LIKE '%".$keyword."%' OR user.username LIKE '%".$keyword."%')  ";
+			}
+		}
+		//Search advanced
+		if(isset($_GET['submit_advanced'])){
+			$keyword_category = Database::escape_string(trim($_GET['keyword_category']));
+			$keyword_request_user = Database::escape_string(trim($_GET['keyword_request_user']));
+			$keyword_admin = Database::escape_string(trim($_GET['keyword_admin']));
+			$keyword_start_date_start = Database::escape_string(trim($_GET['keyword_start_date_start']));		
+			$keyword_start_date_end = Database::escape_string(trim($_GET['keyword_start_date_end']));
+			$keyword_status = Database::escape_string(trim($_GET['keyword_status']));
+			$keyword_source = Database::escape_string(trim($_GET['keyword_source']));
+			$keyword_priority = Database::escape_string(trim($_GET['keyword_priority']));
+			$keyword_range = Database::escape_string(trim($_GET['keyword_dates']));
+			$keyword_course = Database::escape_string(trim($_GET['keyword_course']));
+
+			if($keyword_category !=''){
+				$sql.=" AND ticket.category_id = '$keyword_category'  ";				
+			}
+			if($keyword_request_user !=''){
+				$sql.=" AND (ticket.request_user = '$keyword_request_user' OR user.firstname LIKE '%".$keyword_request_user."%' OR user.official_code LIKE '%".$keyword_request_user."%' OR user.lastname LIKE '%".$keyword_request_user."%'  OR concat(user.firstname,' ',user.lastname) LIKE '%".$keyword_request_user."%'  OR concat(user.lastname,' ',user.firstname) LIKE '%".$keyword_request_user."%' OR user.username LIKE '%".$keyword_request_user."%') ";
+			}
+			if($keyword_admin !=''){
+				$sql.=" AND ticket.assigned_last_user = '$keyword_admin'  ";				
+			}
+			if($keyword_status !=''){
+				$sql.=" AND ticket.status_id = '$keyword_status'  ";				
+			}	
+			if($keyword_range == '' && $keyword_start_date_start!=''){
+				$sql.= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') = '$keyword_start_date_start' ";
+			}
+			if ($keyword_range == '1' && $keyword_start_date_start!='' && $keyword_start_date_end !=''){
+				$sql.= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start' AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') <= '$keyword_start_date_end'";
+			}
+			if ($keyword_priority != ''){
+				$sql.=" AND ticket.priority_id = '$keyword_priority'  ";				
+			}
+			if($keyword_source != ''){
+				$sql.= " AND ticket.source = '$keyword_source' ";
+			}
+			if($keyword_priority != ''){
+				$sql.= " AND ticket.priority_id = '$keyword_priority' ";
+			}
+			if ($keyword_course != ''){
+				$course_table = Database :: get_main_table(TABLE_MAIN_COURSE);
+				$sql .= " AND ticket.course_id IN ( ";
+				$sql .= "SELECT id FROM $course_table WHERE (title LIKE '%".$keyword_course."%' OR code LIKE '%".$keyword_course."%' OR visual_code LIKE '%".$keyword_course."%' )) ";
+			}
+
+		}
+		if($keyword_unread == 'yes'){
+			$sql.= " AND ticket.ticket_id IN (SELECT ticket.ticket_id FROM  $table_support_tickets ticket,  $table_support_messages message,  $table_main_user user WHERE ticket.ticket_id = message.ticket_id   AND message.status = 'NOL'   AND message.sys_insert_user_id = user.user_id   AND user.user_id NOT IN (SELECT user_id FROM $table_main_admin)    AND ticket.status_id != 'REE'   GROUP BY ticket.ticket_id)";
+		}else if($keyword_unread == 'no'){
+			$sql.= " AND ticket.ticket_id NOT IN (SELECT ticket.ticket_id FROM  $table_support_tickets ticket,  $table_support_messages message,  $table_main_user user WHERE ticket.ticket_id = message.ticket_id   AND message.status = 'NOL'   AND message.sys_insert_user_id = user.user_id   AND user.user_id NOT IN (SELECT user_id FROM $table_main_admin)   AND ticket.status_id != 'REE'   GROUP BY ticket.ticket_id)";
+		}
+		$sql .= " ORDER BY col$column $direction";
+		$sql .= " LIMIT $from,$number_of_items";
+		$result = Database::query($sql);
+		$tickets = array();
+		while ($row = Database::fetch_assoc($result)){
+			$sql_unread = "SELECT COUNT(DISTINCT message.message_id) AS unread FROM ".$table_support_tickets."  ticket, ".$table_support_messages." message, ".$table_main_user." user
+ 			WHERE ticket.ticket_id = message.ticket_id AND ticket.ticket_id= '".$row['col0']."' AND message.status='NOL' AND message.sys_insert_user_id = user.user_id ";
+			if($isAdmin){
+				$sql_unread .=" AND user.user_id  NOT IN (SELECT user_id FROM $table_main_admin)   AND ticket.status_id != 'REE' ";
+			}else{				
+				$sql_unread .=" AND user.user_id IN (SELECT user_id FROM $table_main_admin)   ";
+			}
+			$result_unread = Database::query($sql_unread);
+			$unread = Database::fetch_object($result_unread)->unread;
+			$userinfo = UserManager::get_user_info_by_id($row['user_id']);
+			$name = '<a href="'.api_get_path(WEB_PATH).'main/admin/user_information.php?user_id='.$row['user_id'].'">'.api_get_person_name($userinfo['firstname'], $userinfo['lastname']).'</a>';
+			$actions = "";			
+			/*if($row['status_id']!='CLS' && $row['status_id']!='REE'){						
+				if( $row['responsable'] != 0 && $row['responsable'] == $user_id ){
+					$actions = '<a href="myticket.php?ticket_id='.$row['ticket_id'].'&amp;action=unassign" title="desasignarme"><img src="../../../main/img/admin_star.png" border="0" /></a>';					
+				}else{	
+					$actions = '<a href="myticket.php?ticket_id='.$row['ticket_id'].'&amp;action=assign" title="asignarme"><img src="../../../main/img/admin_star_na.png" border="0" /></a>';				
+				}
+			}*/
+			if( $row['responsable'] != 0){
+				$row['responsable']= api_get_user_info($row['responsable']);
+				$row['responsable']= '<a href="'.api_get_path(WEB_PATH).'main/admin/user_information.php?user_id='.$row['responsable']['user_id'].'">'.$row['responsable']['firstname'].' '.$row['responsable']['lastname'].'</a>';
+			}else if($row['status_id']!='REE'){
+				$row['responsable'] = '<span style="color:#ff0000;">Por Asignar</span>';
+			}else{
+				$row['responsable'] = '<span style="color:#00ff00;">REENVIADO</span>';
+			}
+			switch ($row['source']){
+				case 'PRE':
+					$img_source = '../img/icons/32/user.png';
+					break;
+				case 'MAI':
+					$img_source = '../img/icons/32/mail.png';
+					break;
+				case 'TEL':
+					$img_source = '../img/icons/32/event.png';
+					break;
+				default:
+					$img_source = '../img/icons/32/course_home.png';
+					break;
+			}
+			$row['col1'] = api_get_local_time($row['col1']);
+			$row['col2'] = api_get_local_time($row['col2']);
+			if($isAdmin){
+				$actions .= '<a href="ticket_details.php?ticket_id='.$row['col0'].'">'.Display::return_icon('synthese_view.gif', get_lang('Info')).'</a>&nbsp;&nbsp;';
+				if($row['priority_id']=='ALT' && $row['status_id']!='CLS') $actions .= '<img src="../../../main/img/exclamation.png" border="0" />';
+				$row['col0'] = Display::return_icon($img_source, get_lang('Info')).'<a href="ticket_details.php?ticket_id='.$row['col0'].'">'.$row['ticket_code'].'</a>';
+				if($row['col7']=='PENDIENTE'){
+					$row['col7'] = '<span style="color: #f00; font-weight:bold;">'.$row['col7'].'</span>';
+				}
+				//programa: $userinfo['extra']['programa']
+				$ticket=array($row['col0'],api_format_date($row['col1'],'%d/%m/%y - %I:%M:%S %p'),api_format_date($row['col2'],'%d/%m/%y - %I:%M:%S %p'),$row['col3'],$name,$row['responsable'],$row['col7'],$row['col8'],$actions, eregi_replace("[\n|\r|\n\r|\r\n]", ' ', strip_tags($row['col9'])) );
+			}else{
+				$actions ="";
+				$actions .= '<a href="ticket_details.php?ticket_id='.$row['col0'].'">'.Display::return_icon('synthese_view.gif', get_lang('Info')).'</a>&nbsp;&nbsp;';
+				$row['col0'] =Display::return_icon($img_source, get_lang('Info')).'<a href="ticket_details.php?ticket_id='.$row['col0'].'">'.$row['ticket_code'].'</a>';
+				$now = api_strtotime(api_get_utc_datetime());
+				$last_edit_date = api_strtotime($row['sys_lastedit_datetime']);
+				$dif = $now - $last_edit_date ;
+
+				if($dif > 172800 && $row['priority_id'] == 'NRM' && $row['status_id']!='CLS'){
+					$actions .= '<a href="myticket.php?ticket_id='.$row['ticket_id'].'&amp;action=alert"><img src="../../../main/img/exclamation.png" border="0" /></a>';
+				}
+				if($row['priority_id']=='ALT') $actions .= '<img src="../../../main/img/admin_star.png" border="0" />';
+				$ticket=array($row['col0'],api_format_date($row['col1'],'%d/%m/%y - %I:%M:%S %p'),api_format_date($row['col2'],'%d/%m/%y - %I:%M:%S %p'),$row['col3'],$row['col7'],$actions);
+			}
+			if($unread > 0){
+
+				$ticket['0']=$ticket['0'].'&nbsp;&nbsp;('.$unread.')<a href="ticket_details.php?ticket_id='.$row['ticket_id'].'"><img src="../../../main/img/message_new.png" border="0" title="'.$unread.' Nuevo(s) Mensajes"/></a>';
+
+			}
+			if ($isAdmin)
+			$ticket['0'].= '&nbsp;&nbsp;<a  href="javascript:void(0)" onclick="load_history_ticket(\'div_'.$row['ticket_id'].'\','.$row['ticket_id'].')">
+					<img onclick="load_course_list(\'div_'.$row['ticket_id'].'\','.$row['ticket_id'].')" onmouseover="clear_course_list (\'div_'.$row['ticket_id'].'\')" src="../../../main/img/history.gif" title="'.get_lang('Historial').'" alt="'.get_lang('Historial').'"/>
+					<div class="blackboard_hide" id="div_'.$row['ticket_id'].'">&nbsp;&nbsp;</div>
+					</a>&nbsp;&nbsp;';
+			$tickets[] = $ticket;
+		}
+		return $tickets;
+	}
+	public static function get_total_tickets_by_user_id($user_id=null){
+		$table_support_category = Database::get_main_table(TABLE_SUPPORT_CATEGORY);
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$table_support_priority = Database::get_main_table(TABLE_SUPPORT_PRIORITY);
+		$table_support_status = Database::get_main_table(TABLE_SUPPORT_STATUS);
+		$table_support_messages = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+		$table_main_user = Database::get_main_table(TABLE_MAIN_USER);
+		$table_main_admin = Database::get_main_table(TABLE_MAIN_ADMIN);
+		if(is_null($user_id) || $user_id==0){
+			$user_id = api_get_user_id();
+		}
+		$sql = "SELECT COUNT(ticket.ticket_id) AS total	FROM ".$table_support_tickets." ticket ,".$table_support_category." cat , ".$table_support_priority ." priority, ".$table_support_status ." status , ".Database::get_main_table(TABLE_MAIN_USER)." user
+				WHERE cat.category_id = ticket.category_id AND ticket.priority_id = priority.priority_id AND ticket.status_id = status.status_id  AND user.user_id = ticket.request_user ";
+		if(!api_is_platform_admin()){
+			$sql.=" AND request_user = '$user_id' ";
+		}
+
+		//Search simple
+		if(isset($_GET['submit_simple'])){
+			if($_GET['keyword']!=''){
+				$keyword = Database::escape_string(trim($_GET['keyword']));
+				$sql.=" AND (ticket.ticket_code = '".$keyword."' OR user.firstname LIKE '%".$keyword."%' OR user.lastname LIKE '%".$keyword."%'  OR concat(user.firstname,' ',user.lastname) LIKE '%".$keyword."%'  OR concat(user.lastname,' ',user.firstname) LIKE '%".$keyword."%' OR user.username LIKE '%".$keyword."%')  ";
+			}
+		}
+		$keyword_unread = Database::escape_string(trim($_GET['keyword_unread']));
+		//Search advanced
+		if(isset($_GET['submit_advanced'])){
+			$keyword_category = Database::escape_string(trim($_GET['keyword_category']));
+			$keyword_request_user = Database::escape_string(trim($_GET['keyword_request_user']));
+			$keyword_admin = Database::escape_string(trim($_GET['keyword_admin']));
+			$keyword_start_date_start = Database::escape_string(trim($_GET['keyword_start_date_start']));
+			$keyword_start_date_end = Database::escape_string(trim($_GET['keyword_start_date_end']));
+			$keyword_status = Database::escape_string(trim($_GET['keyword_status']));
+			$keyword_source = Database::escape_string(trim($_GET['keyword_source']));
+			$keyword_priority = Database::escape_string(trim($_GET['keyword_priority']));
+			$keyword_range = Database::escape_string(trim($_GET['keyword_dates']));
+			$keyword_course = Database::escape_string(trim($_GET['keyword_course']));				
+
+			if($keyword_category !=''){
+				$sql.=" AND ticket.category_id = '$keyword_category'  ";
+			}
+			if($keyword_request_user !=''){
+			$sql.=" AND (ticket.request_user = '$keyword_request_user' OR user.firstname LIKE '%".$keyword_request_user."%' OR user.official_code LIKE '%".$keyword_request_user."%' OR user.lastname LIKE '%".$keyword_request_user."%'  OR concat(user.firstname,' ',user.lastname) LIKE '%".$keyword_request_user."%'  OR concat(user.lastname,' ',user.firstname) LIKE '%".$keyword_request_user."%' OR user.username LIKE '%".$keyword_request_user."%') ";
+			}
+				if($keyword_admin !=''){
+				$sql.=" AND ticket.assigned_last_user = '$keyword_admin'  ";
+			}
+			if($keyword_status !=''){
+			$sql.=" AND ticket.status_id = '$keyword_status'  ";
+			}
+			if($keyword_range == '' && $keyword_start_date_start!=''){
+			$sql.= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') = '$keyword_start_date_start' ";
+			}
+			if ($keyword_range == '1' && $keyword_start_date_start!='' && $keyword_start_date_end !=''){
+					$sql.= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start' AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') <= '$keyword_start_date_end'";
+			}
+							if ($keyword_priority != ''){
+			$sql.=" AND ticket.priority_id = '$keyword_priority'  ";
+			}
+			if($keyword_source != ''){
+			$sql.= " AND ticket.source = '$keyword_source' ";
+			}
+			if($keyword_priority != ''){
+			$sql.= " AND ticket.priority_id = '$keyword_priority' ";
+			}
+			if ($keyword_course != ''){
+				$course_table = Database :: get_main_table(TABLE_MAIN_COURSE);
+				$sql .= " AND ticket.course_id IN ( ";
+				$sql .= "SELECT id FROM $course_table WHERE (title LIKE '%".$keyword_course."%' OR code LIKE '%".$keyword_course."%' OR visual_code LIKE '%".$keyword_course."%' )) ";
+			}
+
+		}
+		if($keyword_unread == 'yes'){
+			$sql.= " AND ticket.ticket_id IN (SELECT ticket.ticket_id FROM  $table_support_tickets ticket,  $table_support_messages message,  $table_main_user user WHERE ticket.ticket_id = message.ticket_id   AND message.status = 'NOL'   AND message.sys_insert_user_id = user.user_id   AND user.user_id NOT IN (SELECT user_id FROM $table_main_admin)    AND ticket.status_id != 'REE'   GROUP BY ticket.ticket_id)";
+		}else if($keyword_unread == 'no'){
+			$sql.= " AND ticket.ticket_id NOT IN (SELECT ticket.ticket_id FROM  $table_support_tickets ticket,  $table_support_messages message,  $table_main_user user WHERE ticket.ticket_id = message.ticket_id   AND message.status = 'NOL'   AND message.sys_insert_user_id = user.user_id   AND user.user_id NOT IN (SELECT user_id FROM $table_main_admin)   AND ticket.status_id != 'REE'   GROUP BY ticket.ticket_id)";
+		}
+		$res = Database::query($sql);
+		$obj = Database::fetch_object($res);
+		return $obj->total;
+	}
+	public static function get_ticket_detail_by_id($ticket_id,$user_id){
+		$table_support_category = Database::get_main_table(TABLE_SUPPORT_CATEGORY);
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$table_support_priority = Database::get_main_table(TABLE_SUPPORT_PRIORITY);
+		$table_support_status = Database::get_main_table(TABLE_SUPPORT_STATUS);
+		$table_support_messages = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+		$table_support_message_attachments = Database::get_main_table(TABLE_SUPPORT_MESSAGE_ATTACHMENTS);
+
+		$sql =  "SELECT ticket.* ,cat.name , status.name as status, priority.priority FROM ".$table_support_tickets." ticket, ".$table_support_category." cat ,".$table_support_priority." priority , ".$table_support_status." status 
+		WHERE ticket.ticket_id = '$ticket_id' AND cat.category_id = ticket.category_id AND priority.priority_id = ticket.priority_id AND status.status_id = ticket.status_id  ";
+		if(!UserManager::is_admin($user_id)){
+			$sql.= "AND ticket.request_user = '$user_id'";
+		}
+		$result = Database::query($sql);
+		$ticket = array();
+		if(Database::num_rows($result)>0){
+			while ($row = Database::fetch_assoc($result)){
+				$row['course'] =  null;
+				$row['start_date'] = api_convert_and_format_date(api_get_local_time($row['start_date']), DATE_TIME_FORMAT_LONG,_api_get_timezone());
+				$row['end_date'] = api_convert_and_format_date(api_get_local_time($row['end_date']), DATE_TIME_FORMAT_LONG,_api_get_timezone());
+				$row['sys_lastedit_datetime'] = api_convert_and_format_date(api_get_local_time($row['sys_lastedit_datetime']), DATE_TIME_FORMAT_LONG,_api_get_timezone());
+				$row['course_url'] = null;
+				if($row['course_id']!=0){
+					$course = api_get_course_info_by_id($row['course_id']);
+					$row['course_url']	= '<a href="'.api_get_path(WEB_COURSE_PATH).$course['path'].'">'.$course['name'].'</a>';
+				}
+				$userinfo = api_get_user_info($row['request_user']);
+				$row['user_url'] = '<a href="'.api_get_path(WEB_PATH).'main/admin/user_information.php?user_id='.$row['request_user'].'">'.api_get_person_name($userinfo['firstname'], $userinfo['lastname']).'</a>';
+				$ticket['usuario'] = $userinfo;
+				$ticket['ticket']= $row;
+			}
+			$sql = "SELECT  * FROM ".$table_support_messages." message, ".Database::get_main_table(TABLE_MAIN_USER)." user  WHERE message.ticket_id = '$ticket_id' AND message.sys_insert_user_id = user.user_id ";
+			$result = Database::query($sql);
+			$ticket['messages']= array();
+			$attach_icon = Display::return_icon('attachment.gif', '');
+			$admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
+			while ($row = Database::fetch_assoc($result)){
+				$message = $row;				
+				//Check if user is an admin
+				$sql_admin = "SELECT user_id FROM $admin_table
+				WHERE user_id = '".intval($message['user_id'])."' LIMIT 1";
+				$result_admin = Database::query($sql_admin);
+				$message['admin'] = false;
+				if (Database::num_rows($result_admin) > 0) {
+				$message['admin'] = true;
+				}
+				$message['user_created']= '<a href="'.api_get_path(WEB_PATH).'main/admin/user_information.php?user_id='.$row['user_id'].'">'.$row['firstname'].' '.$row['lastname'].'</a>';
+				$sql_atachment ="SELECT * FROM ".TABLE_SUPPORT_MESSAGE_ATTACHMENTS." WHERE message_id = ".$row['message_id']." AND ticket_id= '$ticket_id'  ";
+				$result_attach = Database::query($sql_atachment);
+				while ($row2 = Database::fetch_assoc($result_attach)){
+					$archiveURL =$archiveURL=api_get_path(WEB_PLUGIN_PATH).PLUGIN_NAME.'/s/download.php?ticket_id='.$ticket_id.'&file=';
+					$row2['attachment_link']= 	$attach_icon.'&nbsp;<a href="'.$archiveURL.$row2['path'].'&title='.$row2['filename'].'">'.$row2['filename'].'</a>&nbsp;('.$row2['size'].')';
+					$message['atachments'][]= $row2;
+				}
+				$ticket['messages'][] = $message;
+			}
+		}
+		return $ticket;	
+	}
+	public static function assign_ticket_user($ticket_id, $user_id){
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$table_support_assigned_log = Database::get_main_table(TABLE_SUPPORT_ASSIGNED_LOG);
+		$now = api_get_utc_datetime();			
+		$sql_update = "UPDATE ".$table_support_tickets." SET  assigned_last_user = '$user_id'  WHERE ticket_id = '$ticket_id' ";
+		Database::query($sql_update);
+		if(Database::affected_rows()>0){
+			$insert_id = api_get_user_id();
+			$sql ="INSERT INTO ".$table_support_assigned_log." (ticket_id , user_id , assigned_date , sys_insert_user_id) VALUES ('$ticket_id','$user_id','".$now."','$insert_id');";
+			Database::query($sql);
+			if ($insert_id != $user_id){
+				$info = api_get_user_info($user_id);
+				$mensaje = '<p>Estimado(a):</p><p>'.$info['firstname']." ".$info['lastname']."</p>
+							<p>Te asignaron el ticket $ticket_id ".'<a href="'.api_get_path(WEB_PLUGIN_PATH).PLUGIN_NAME.'/s/ticket_details.php?ticket_id='.$ticket_id.'">Ticket</a></p>
+							<p>Centro de Educaci&oacute;n Virtual</p>';
+				api_mail_html($info['firstname']." ".$info['lastname'], $info['mail'],  "[TICKETS] Asignacion de Ticket #$ticket_id ", $mensaje,'Plataforma Virtual', 'plataformavirtual@usil.edu.pe', array('cc'=>'plataformavirtual@usil.edu.pe'));
+			}
+		}
+	}
+	public static function update_message_status($ticket_id,$user_id){
+		$table_support_messages = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+		$sql = "UPDATE ".$table_support_messages." SET status = 'LEI' , sys_lastedit_user_id ='".api_get_user_id()."' ,sys_lastedit_datetime ='".$now."' WHERE ticket_id ='$ticket_id' ";
+		
+		if(api_is_platform_admin()){
+			$sql .= " AND sys_insert_user_id = '$user_id'";
+		}else{
+
+			$sql .= " AND sys_insert_user_id != '$user_id'";
+		}
+		Database::query($sql);
+		if(Database::affected_rows()>0){
+			Database::query("UPDATE ".Database::get_main_table(TABLE_SUPPORT_TICKET)." SET status_id = 'PND'  WHERE ticket_id ='$ticket_id' AND status_id = 'NAT'");
+			return true;
+		}else{
+			return false;
+		}	
+	}
+	public static function update_ticket_status($status_id,$ticket_id, $user_id){
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$table_support_messages = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+		$now = api_get_utc_datetime();
+		$sql = "UPDATE ".$table_support_tickets." SET status_id = '$status_id' , sys_lastedit_user_id ='$user_id' ,sys_lastedit_datetime ='".$now."'  WHERE ticket_id ='$ticket_id'";
+		Database::query($sql);
+		if(Database::affected_rows()>0){
+			return true;
+		}else{
+			return false;
+		}	
+	}
+	public static function get_number_of_messages(){
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$table_support_messages = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+		$table_main_user = Database::get_main_table(TABLE_MAIN_USER);
+		$table_main_admin = Database::get_main_table(TABLE_MAIN_ADMIN);
+		$user_info = api_get_user_info();
+		$user_id = $user_info['user_id'];
+		$sql ="SELECT COUNT( DISTINCT ticket.ticket_id) AS unread  FROM ".$table_support_tickets." ticket, ".$table_support_messages." message , ".$table_main_user." user WHERE ticket.ticket_id = message.ticket_id AND message.status = 'NOL'    AND user.user_id = message.sys_insert_user_id ";
+		if(!api_is_platform_admin()){
+			$sql .=" AND ticket.request_user = '$user_id'  AND user_id IN (SELECT user_id FROM $table_main_admin)  ";
+		}else{
+			$sql .=" AND user_id NOT IN (SELECT user_id FROM $table_main_admin) AND ticket.status_id != 'REE'";
+		}
+		$sql .= "  AND ticket.project_id != '' ";
+		$res = Database::query($sql);
+		$obj = Database::fetch_object($res);
+		return $obj->unread;
+
+	}
+	public static function send_alert($ticket_id,$user_id){
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$now = api_get_utc_datetime();
+		$sql = "UPDATE ".$table_support_tickets." SET priority_id = 'ALT', sys_lastedit_user_id ='$user_id' ,sys_lastedit_datetime ='".$now."' WHERE ticket_id = '$ticket_id'";	
+		Database::query($sql);	
+	}
+	public static function close_ticket($ticket_id, $user_id){
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$now = api_get_utc_datetime();
+		$sql = "UPDATE ".$table_support_tickets." SET status_id = 'CLS' , sys_lastedit_user_id ='$user_id' ,sys_lastedit_datetime ='".$now."' ,end_date ='".$now."' WHERE ticket_id ='$ticket_id'";
+		Database::query($sql);		
+	}
+	public static function close_old_tickets(){
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$now = api_get_utc_datetime();
+		$sql = "UPDATE ".$table_support_tickets." SET status_id = 'CLS' , sys_lastedit_user_id ='".api_get_user_id()."' ,sys_lastedit_datetime ='".$now."',end_date ='".$now."' WHERE DATEDIFF('$now',sys_lastedit_datetime) > 7 AND status_id != 'CLS' AND status_id != 'NAT' AND status_id != 'REE'";
+		Database::query($sql);		
+	}
+	public static function get_assign_log($ticket_id){
+		$table_support_assigned_log = Database::get_main_table(TABLE_SUPPORT_ASSIGNED_LOG);
+		$sql = "SELECT log.* FROM ".TABLE_SUPPORT_ASSIGNED_LOG." log  WHERE log.ticket_id = '$ticket_id' ORDER BY log.assigned_date";
+		$result = Database::query($sql);
+		$history = array();
+		while ($row = Database::fetch_assoc($result)){
+			if ($row['user_id'] != 0) $assignuser = api_get_user_info($row['user_id']);
+			$insertuser = api_get_user_info($row['sys_insert_user_id']);
+			$row['assigned_date'] = api_convert_and_format_date(api_get_local_time($row['assigned_date']), '%d/%m/%y-%H:%M:%S',_api_get_timezone());
+			$row['assignuser']= ($row['user_id'] != 0)?('<a href="'.api_get_path(WEB_PATH).'main/admin/user_information.php?user_id='.$row['user_id'].'"  target="_blank">'.$assignuser['username'].'</a>') : get_lang('Unassign');
+			$row['insertuser']= '<a href="'.api_get_path(WEB_PATH).'main/admin/user_information.php?user_id='.$row['sys_insert_user_id'].'"  target="_blank">'.$insertuser['username'].'</a>';
+			$history[]=$row;
+		}
+		return $history;
+	}
+	public static function export_tickets_by_user_id($from, $number_of_items, $column, $direction ,$user_id=null){
+		$table_support_category = Database::get_main_table(TABLE_SUPPORT_CATEGORY);
+		$table_support_tickets = Database::get_main_table(TABLE_SUPPORT_TICKET);
+		$table_support_priority = Database::get_main_table(TABLE_SUPPORT_PRIORITY);
+		$table_support_status = Database::get_main_table(TABLE_SUPPORT_STATUS);
+		$table_support_messages = Database::get_main_table(TABLE_SUPPORT_MESSAGE);
+		$table_main_user = Database::get_main_table(TABLE_MAIN_USER);
+		if(is_null($direction)) $direction ="DESC";
+		if(is_null($user_id) || $user_id==0){
+			$user_id = api_get_user_id();
+		}
+
+		$sql = "SELECT ticket.ticket_code, ticket.sys_insert_datetime , ticket.sys_lastedit_datetime , cat.name as category , CONCAT(user.lastname,' ', user.firstname) AS fullname , status.name as status , ticket.total_messages as messages , ticket.assigned_last_user as responsable
+				FROM ".$table_support_tickets." ticket ,".$table_support_category." cat , ".$table_support_priority ." priority, ".$table_support_status ." status , ".Database::get_main_table(TABLE_MAIN_USER)." user
+				WHERE cat.category_id = ticket.category_id AND ticket.priority_id = priority.priority_id AND ticket.status_id = status.status_id  AND user.user_id = ticket.request_user ";
+		//Search simple
+		if(isset($_GET['submit_simple'])){
+			if($_GET['keyword']!=''){
+				$keyword = Database::escape_string(trim($_GET['keyword']));
+				$sql.=" AND (ticket.ticket_code = '".$keyword."' OR user.firstname LIKE '%".$keyword."%' OR user.lastname LIKE '%".$keyword."%'  OR concat(user.firstname,' ',user.lastname) LIKE '%".$keyword."%'  OR concat(user.lastname,' ',user.firstname) LIKE '%".$keyword."%' OR user.username LIKE '%".$keyword."%')  ";
+			}
+		}
+		//Search advanced
+		if(isset($_GET['submit_advanced'])){
+			$keyword_category = Database::escape_string(trim($_GET['keyword_category']));
+			$keyword_request_user = Database::escape_string(trim($_GET['keyword_request_user']));
+			$keyword_admin = Database::escape_string(trim($_GET['keyword_admin']));
+			$keyword_start_date_start = Database::escape_string(trim($_GET['keyword_start_date_start']));
+			$keyword_start_date_end = Database::escape_string(trim($_GET['keyword_start_date_end']));
+			$keyword_status = Database::escape_string(trim($_GET['keyword_status']));
+			$keyword_source = Database::escape_string(trim($_GET['keyword_source']));
+			$keyword_priority = Database::escape_string(trim($_GET['keyword_priority']));
+			$keyword_range = Database::escape_string(trim($_GET['keyword_dates']));
+			$keyword_unread = Database::escape_string(trim($_GET['keyword_unread']));
+			$keyword_course = Database::escape_string(trim($_GET['keyword_course']));
+
+			if($keyword_category !=''){
+				$sql.=" AND ticket.category_id = '$keyword_category'  ";
+			}
+			if($keyword_request_user !=''){
+			$sql.=" AND (ticket.request_user = '$keyword_request_user' OR user.firstname LIKE '%".$keyword_request_user."%' OR user.official_code LIKE '%".$keyword_request_user."%' OR user.lastname LIKE '%".$keyword_request_user."%'  OR concat(user.firstname,' ',user.lastname) LIKE '%".$keyword_request_user."%'  OR concat(user.lastname,' ',user.firstname) LIKE '%".$keyword_request_user."%' OR user.username LIKE '%".$keyword_request_user."%') ";
+			}
+			if($keyword_admin !=''){
+			$sql.=" AND ticket.assigned_last_user = '$keyword_admin'  ";
+			}
+			if($keyword_status !=''){
+			$sql.=" AND ticket.status_id = '$keyword_status'  ";
+			}
+			if($keyword_range == '' && $keyword_start_date_start!=''){
+			$sql.= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') = '$keyword_start_date_start' ";
+			}
+			if ($keyword_range == '1' && $keyword_start_date_start!='' && $keyword_start_date_end !=''){
+			$sql.= " AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') >= '$keyword_start_date_start' AND DATE_FORMAT( ticket.start_date,'%d/%m/%Y') <= '$keyword_start_date_end'";
+			}
+					if ($keyword_priority != ''){
+			$sql.=" AND ticket.priority_id = '$keyword_priority'  ";
+			}
+			if($keyword_source != ''){
+			$sql.= " AND ticket.source = '$keyword_source' ";
+			}
+			if($keyword_priority != ''){
+			$sql.= " AND ticket.priority_id = '$keyword_priority' ";
+			}
+			if ($keyword_course != ''){
+				$course_table = Database :: get_main_table(TABLE_MAIN_COURSE);
+				$sql .= " AND ticket.course_id IN ( ";
+				$sql .= "SELECT id FROM $course_table WHERE (title LIKE '%".$keyword_course."%' OR code LIKE '%".$keyword_course."%' OR visual_code LIKE '%".$keyword_course."%' )) ";
+			}
+			if($keyword_unread == 'yes'){
+			$sql.= " AND ticket.ticket_id IN (SELECT ticket.ticket_id FROM  $table_support_tickets ticket,  $table_support_messages message,  $table_main_user user WHERE ticket.ticket_id = message.ticket_id   AND message.status = 'NOL'   AND message.sys_insert_user_id = user.user_id   AND user.status != 1   AND ticket.status_id != 'REE'   GROUP BY ticket.ticket_id)";
+			}else if($keyword_unread == 'no'){
+			$sql.= " AND ticket.ticket_id NOT IN (SELECT ticket.ticket_id FROM  $table_support_tickets ticket,  $table_support_messages message,  $table_main_user user WHERE ticket.ticket_id = message.ticket_id   AND message.status = 'NOL'   AND message.sys_insert_user_id = user.user_id   AND user.status != 1   AND ticket.status_id != 'REE'   GROUP BY ticket.ticket_id)";
+			}	
+
+		}
+
+
+		//$sql .= " ORDER BY col$column $direction";
+		$sql .= " LIMIT $from,$number_of_items";
+
+		$result = Database::query($sql);
+		$tickets[0] =  array(utf8_decode('Ticket#'), utf8_decode('Fecha'), utf8_decode('Fecha Edicion'), utf8_decode('Categoria'), utf8_decode('Usuario'), utf8_decode('Estado'), utf8_decode('Mensajes'), utf8_decode('Responsable') , utf8_decode('Programa') ) ;
+
+		while ($row = Database::fetch_assoc($result)){
+			if( $row['responsable'] != 0){
+				$row['responsable']= api_get_user_info($row['responsable']);
+				$row['responsable']= $row['responsable']['firstname'].' '.$row['responsable']['lastname'];
+			}
+			$row['sys_insert_datetime'] = api_format_date($row['sys_insert_datetime'],'%d/%m/%y - %I:%M:%S %p');
+			$row['sys_lastedit_datetime'] = api_format_date($row['sys_lastedit_datetime'],'%d/%m/%y - %I:%M:%S %p');
+			$row['category'] = utf8_decode($row['category']);
+			$row['programa'] = utf8_decode($row['fullname']);
+			$row['fullname'] = utf8_decode($row['fullname']);
+			$row['responsable'] = utf8_decode($row['responsable']);
+			$tickets[] = $row;
+		}
+		return $tickets;
+	}
+}
+?>

+ 26 - 0
plugin/ticket/s/ticket_assign_log.php

@@ -0,0 +1,26 @@
+<?php
+$language_file = array ('registration');
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+$ticket_id = intval($_POST['ticket_id']);
+$history = TicketManager::get_assign_log($ticket_id);
+?>
+<table width="350px" border="0" cellspacing="2" cellpadding="2">
+<?php
+if (count($history)==0) {
+?>
+<tr>
+	<td colspan="2"><?php echo api_ucfirst(('Sin Historial')); ?></td>
+</tr>
+<?php
+}
+?>
+<?php for($k=0;$k<count($history);$k++) { ?>
+    <tr>
+        <td width="125px"><?php echo api_convert_encoding($history[$k]['assignuser'],'UTF-8',$charset);?></td>
+        <td width="100px"><?php echo api_convert_encoding($history[$k]['assigned_date'],'UTF-8',$charset);?></td>
+        <td width="125px"><?php echo api_convert_encoding($history[$k]['insertuser'],'UTF-8',$charset);?></td>
+    </tr>
+<?php }?>
+</table>

+ 357 - 0
plugin/ticket/s/ticket_details.php

@@ -0,0 +1,357 @@
+<?php
+$language_file= array('messages','userInfo', 'admin');
+$cidReset	= true;
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+api_block_anonymous_users();
+$interbreadcrumb[]= array ('url' =>'myticket.php','name' => get_lang('MisTickets'));
+$interbreadcrumb[]= array ('url' =>'#','name' => get_lang('TicketDetail'));
+$htmlHeadXtra[]='
+<script src="/pie/PIE_IE678.js"></script>
+<script language="javascript">
+$(document).ready(function(){
+	$( "#dialog-form" ).dialog({
+		autoOpen: false,
+		height: 450,
+		width: 600,
+		modal: true,
+		buttons: {
+			Asignar: function(){
+				$("#genesis").submit()
+				},
+			 Close: function() {
+                    $( this ).dialog( "close" );
+             }
+		}
+		
+	});
+    	$("a#assign").click(function () {
+		$( "#dialog-form" ).dialog( "open" );
+        
+    	});
+		$("input#respuestasi").click(function () {
+			if(!confirm("Confirma que su respuesta es : SI ?. Si est\u00e1 seguro el ticket ser\u00e1 cerrado")){
+				return false;
+			}
+        
+    	});
+		$("input#respuestano").click(function () {
+			if(!confirm("Confirma que su respuesta es : NO ?")){
+				return false;
+			}
+        
+    	});
+	$("#unassign").click(function () {
+        if (!confirm("Estas seguro de Desasignarte")) {
+            return false		
+		}
+    });
+	$("#close").click(function () {
+        if (!confirm("Estas seguro de Cerrar el Ticket")) {
+			return false		
+		}
+    });
+});
+function validate() {	
+	fckEditor1val = FCKeditorAPI.__Instances["content"].GetHTML();	
+	document.getElementById("content").value= fckEditor1val;
+	if(fckEditor1val ==""){
+		alert("Debe escribir un mensaje");
+		return false;
+	}
+}
+var counter_image = 1;
+function remove_image_form(id_elem1) {
+	var elem1 = document.getElementById(id_elem1);
+	elem1.parentNode.removeChild(elem1);
+	counter_image = counter_image - 1;
+}
+function add_image_form() {
+	// Multiple filepaths for image form
+	var filepaths = document.getElementById("filepaths");
+	if (document.getElementById("filepath_"+counter_image)) {
+		counter_image = counter_image + 1;
+	}  else {
+		counter_image = counter_image;
+	}
+	var elem1 = document.createElement("div");
+	elem1.setAttribute("id","filepath_"+counter_image);
+	filepaths.appendChild(elem1);
+	id_elem1 = "filepath_"+counter_image;
+	id_elem1 = "\'"+id_elem1+"\'";
+	document.getElementById("filepath_"+counter_image).innerHTML = "<input type=\"file\" name=\"attach_"+counter_image+"\"  size=\"20\"  />&nbsp;<a href=\"javascript:remove_image_form("+id_elem1+")\"><img src=\"'.api_get_path(WEB_CODE_PATH).'img/delete.gif\"></a>";
+	//document.getElementById("filepath_"+counter_image).innerHTML = "<input type=\"file\" name=\"attach_"+counter_image+"\"  size=\"20\" />&nbsp;<input type=\"text\" name=\"legend[]\" size=\"20\" />";
+	if (filepaths.childNodes.length == 6) {
+		var link_attach = document.getElementById("link-more-attach");
+		if (link_attach) {
+			link_attach.innerHTML="";
+		}
+	}
+}
+</script>';
+$htmlHeadXtra[] = '
+<style>
+div.row div.label2 {
+	float:left;
+	text-align: right;
+	width:22%;
+}
+div.row div.formw2 {
+    width:50%;	
+	margin-left: 2%;	
+	margin-right: 16%;
+	float:left;
+}
+.messageuser, .messagesupport {
+    border: 1px solid;
+    margin: 10px 0px;
+    padding:15px 10px 15px 50px;
+    background-repeat: no-repeat;
+    background-position: 10px center;
+    width:50%;	
+	behavior: url(/pie/PIE.htc);
+}
+.messageuser {
+    color: #00529B;
+    -moz-border-radius: 15px 15px 15px 15px;
+    -webkit-border-radius: 15px 15px 15px 15px;
+    background-color: #BDE5F8;    
+    margin-left:20%;
+    border-radius:15px;
+    float: left;
+}
+.messagesupport {
+    color: #4F8A10;
+    -moz-border-radius: 15px 15px 15px 15px;
+    -webkit-border-radius: 15px 15px 15px 15px;
+    background-color: #DFF2BF;
+    margin-right: 20%;
+    float: right;
+    border-radius:15px;
+}
+
+</style>';
+
+$user_id = api_get_user_id();
+$isAdmin = api_is_platform_admin();
+$ticket_id = $_GET['ticket_id'];
+$ticket = TicketManager::get_ticket_detail_by_id($ticket_id,$user_id);
+if(!isset($ticket['ticket'])){
+	api_not_allowed();
+}
+if(!isset($_GET['ticket_id'])){
+	header('location:myticket.php');
+}
+if(isset($_POST['respuesta'])){
+	if($user_id == $ticket['ticket']['request_user']){
+		$respuesta = ($_POST['respuesta']=='si')?true:(($_POST['respuesta']=='no'?false:null));
+		if ($respuesta  && $ticket['ticket']['status_id'] == 'XCF' ){
+			TicketManager::close_ticket($_GET['ticket_id'], $user_id);
+				$ticket['ticket']['status_id'] = 'CLS';
+				$ticket['ticket']['status'] = 'CERRADO';
+			}else if(!is_null($respuesta) && $ticket['ticket']['status_id'] == 'XCF'){
+				TicketManager::update_ticket_status('PND',$_GET['ticket_id'], $user_id);
+				$ticket['ticket']['status_id'] = 'PND';
+				$ticket['ticket']['status'] = 'PENDIENTE';
+			}
+	}
+	
+}
+if (isset($_REQUEST['action'])){
+	$action = $_REQUEST['action'];
+	switch ($action){
+		case 'assign':
+			if(api_is_platform_admin() && isset($_GET['ticket_id']) )
+				TicketManager::assign_ticket_user($_GET['ticket_id'], $_POST['admins']);
+				$ticket['ticket']['assigned_last_user'] = $_POST['admins'];
+			break;
+		case 'unassign':
+			if(api_is_platform_admin() && isset($_GET['ticket_id']) )
+				TicketManager::assign_ticket_user($_GET['ticket_id'], 0);
+				$ticket['ticket']['assigned_last_user'] = 0;
+			break;
+		default:
+			break;
+	}
+}
+if(!isset($_POST['compose'])){  
+	if(isset($_POST['close'])){
+		$_GET['ticket_id'] = $_POST['ticket_id'] ;
+		TicketManager::close_ticket($_GET['ticket_id'], $user_id);
+		$ticket['ticket']['status_id'] = 'CLS';
+		$ticket['ticket']['status'] = 'CERRADO';
+	}
+	$ticket['ticket']['request_user'] = intval($ticket['ticket']['request_user']);
+	if($ticket['ticket']['request_user'] == $user_id || intval($ticket['ticket']['assigned_last_user']) == $user_id ){
+		TicketManager::update_message_status($ticket_id, $ticket['ticket']['request_user']);
+	}
+	Display::display_header();
+	$form_close_ticket = "";
+	if($ticket['ticket']['status_id'] != 'REE' AND $ticket['ticket']['status_id'] != 'CLS' AND $isAdmin ){
+			if(intval($ticket['ticket']['assigned_last_user']) == $user_id){
+				if($ticket['ticket']['status_id']!='CLS'){
+					$form_close_ticket.= '<form enctype="multipart/form-data" action="'.api_get_self().'?ticket_id='.$ticket['ticket']['ticket_id'].'" method="post" name="close_ticket" id="close_ticket" >';
+					$form_close_ticket.= '<input type="hidden" name="ticket_id" value="'.$ticket['ticket']['ticket_id'].'"/>
+							<button class="minus" name="close" type="submit" id="close" >Cerrar</button>';
+					$form_close_ticket.= '</form>';
+				}
+			}
+		
+	}
+	$titulo = '<center><h1>Ticket #'.$ticket['ticket']['ticket_code'].'</h1></center>';
+	if($isAdmin && $ticket['ticket']['status_id'] != 'CLS' && $ticket['ticket']['status_id'] != 'REE'){
+		if( $ticket['ticket']['assigned_last_user'] != 0 && $ticket['ticket']['assigned_last_user'] == $user_id ){
+			$img_assing = '<a href="'.api_get_self().'?ticket_id='.$ticket['ticket']['ticket_id'].'&amp;action=unassign" id="unassign"><img src="../../../main/img/admin_star.png" border="0" title="Desasignarme" align="center"/></a>';					
+		}else{	
+			$img_assing .= '<a href="#" id="assign"><img src="../../../main/img/admin_star_na.png" border="0" title="Asignar" align="center"/></a>';				
+		}
+	}
+	$negrita = ($ticket['ticket']['status_id'] == 'CLS')?'style = "font-weight: bold;"':'';
+	$cadena = ($ticket['ticket']['status_id'] != 'CLS')?"sas":"";
+	echo '<div style="margin-left:20%;margin-right:20%;">
+			<table width="100%" >
+				<tr>
+	              <td colspan="3" style="width:65%">'.$titulo.'</td>
+	              <td >'.$img_assing.'</td>
+	              <td>'.$form_close_ticket.'</td>
+	            </tr>
+	         	<tr>
+	              <td style="width:45%;" ><p>Enviado  : '.$ticket['ticket']['start_date'].'</p></td>
+	              <td style="width:50px;"></td>
+	              <td style="width:45%;" ><p>Ultima Respuesta  : '.$ticket['ticket']['sys_lastedit_datetime'].'</p></td>
+	              <td colspan="2"></td>
+	            </tr>
+	            <tr>
+	               <td><p>Asunto  : '.$ticket['messages'][0]['subject'].'</p></td>
+	               <td></td>
+	               <td><p '.$negrita.'>Estado : '.$ticket['ticket']['status'].'</p></td>
+	               <td colspan="2"></td>
+	            </tr>
+	            <tr>
+	                <td><p>Categoria  : '.$ticket['ticket']['name'].'</p></td>
+	                <td></td>
+	                <td ><p>Prioridad :'.$ticket['ticket']['priority'].'<p></td>
+	                <td colspan="2"></td>
+	            </tr>';
+	if($ticket['ticket']['course_url']!=null){
+		echo '<tr>
+				<td><p>Curso:</p></td>
+	            <td></td>
+			    <td>'.$ticket['ticket']['course_url'].'</td>
+	            <td colspan="2"></td>
+	          </tr>';
+	}
+	if ($isAdmin){
+		echo '<tr>
+				<td><p>Usuario:</p></td>
+	            <td></td>
+			    <td>'.$user_info = $ticket['ticket']['user_url'].' ('.$ticket['usuario']['username'].')</td>
+	            <td colspan="2"></td>
+			 </tr>';
+	}
+	//select admins
+	$select_admins .= '<select  class ="chzn-select" style="width: 350px; " name = "admins" id="admins" ">';
+	
+	$admins = UserManager::get_user_list_like(array("status"=>"1"),array("username"),true);
+	foreach ($admins as $admin) {
+		$select_admins.= "<option value = '".$admin['user_id']."' ".(($user_id==$admin['user_id'])?("selected='selected'"):"").">".$admin['lastname']." ,".$admin['firstname']."</option>";
+	}
+	$select_admins .= "</select>";
+	echo '<div id="dialog-form" title="Asignar Ticket" >';
+	echo '<form id="genesis" method="POST" action="ticket_details.php?ticket_id='.$ticket['ticket']['ticket_id'].'">
+			<input type="hidden" name ="action" id="action" value="assign"/>
+			<div  class="row">
+				<div class="label">Responsable:</div>
+				<div class="formw">'.$select_admins.'</div>
+			</div>			
+		  </form>';
+	echo '</div>';
+	echo '</table></div>';
+	    $messages = $ticket['messages'];
+	    foreach($messages as $message){
+	        $class ="messageuser";
+	        if($message['admin']){
+	        	$class ="messagesupport";
+	        	if($isAdmin)$message['message'].="<br/><b>Atendido por: ".$message['user_created']." - ".api_convert_and_format_date(api_get_local_time($message['sys_insert_datetime']), DATE_TIME_FORMAT_LONG,_api_get_timezone())."</b>";
+	        }else{
+	        	$message['message'].="<b>Enviado: ".api_convert_and_format_date(api_get_local_time($message['sys_insert_datetime']), DATE_TIME_FORMAT_LONG,_api_get_timezone())."</b>";
+	        }
+	        echo '<div class="'.$class.'" ><b>Asunto: </b> '.$message['subject'].'<br/> <b> Mensaje:</b>'.$message['message'].'<br/>';
+	        if(isset($message['atachments'])){
+		        foreach($message['atachments'] as $attach){
+		                echo $attach['attachment_link'];
+		       }
+		    }
+	        echo '</div>';
+    	}
+    	$asunto = "RE: ".$message['subject'];
+    	$user_admin = api_is_platform_admin();
+    	if($ticket['ticket']['status_id'] != 'REE' AND $ticket['ticket']['status_id'] != 'CLS'  ){
+    		if(!$isAdmin && $ticket['ticket']['status_id'] != 'XCF'){
+    			show_form_send_message();
+    		}else{
+    			if(intval($ticket['ticket']['assigned_last_user']) == $user_id){
+    				show_form_send_message();
+    				$cheked ="";
+    	
+    			}
+    		}
+    	}
+    	
+}else{
+    $ticket_id	= $_POST['ticket_id'];
+    $content	=	$_POST['content'];
+    $subject	=	$_POST['subject'];
+    $mensajeconfirmacion = isset($_POST['confirmacion'])?true:false ; 
+    $file_attachments   =	$_FILES;
+    $user_id = api_get_user_id();
+    TicketManager::insert_message($ticket_id, $subject, $content, $file_attachments, $user_id,'NOL',$mensajeconfirmacion);
+    header("location:".api_get_self()."?ticket_id=".$ticket_id);
+}
+function show_form_send_message(){
+	global $isAdmin;
+	global $ticket;
+	global $asunto;
+    echo '<form enctype="multipart/form-data" action="'.api_get_self().'?ticket_id='.$ticket['ticket']['ticket_id'].'" method="post" name="send_ticket" id="send_ticket"
+ 	onsubmit="return validate()" style="width:100%">';
+	echo '<div class="row" ><div class ="label">Asunto:</div>
+       		<div class="formw"><input type = "text" id ="subject" name="subject" value="'.$asunto.'" required ="" style="width:60%"/></div>
+		  </div>';
+	echo '<div class="row">
+		<div class="label2">mensaje
+		</div>
+		<div class="formw2">
+			<input type="hidden" id="content" name="content" value="" style="display:none">
+		<input type="hidden" id="content___Config" value="ToolbarSet=Messages&amp;Width=95%25&amp;Height=250&amp;ToolbarSets={ %22Messages%22: [  [ %22Bold%22,%22Italic%22,%22-%22,%22InsertOrderedList%22,%22InsertUnorderedList%22,%22Link%22,%22RemoveLink%22 ] ], %22MessagesMaximized%22: [  ] }&amp;LoadPlugin=[%22customizations%22]&amp;EditorAreaStyles=body { background: #ffffff; }&amp;ToolbarStartExpanded=false&amp;CustomConfigurationsPath=/main/inc/lib/fckeditor/myconfig.js&amp;EditorAreaCSS=/main/css/chamilo/default.css&amp;ToolbarComboPreviewCSS=/main/css/chamilo/default.css&amp;DefaultLanguage=es&amp;ContentLangDirection=ltr&amp;AdvancedFileManager=true&amp;BaseHref='.api_get_path(WEB_PLUGIN_PATH).PLUGIN_NAME.'/s/&amp;&amp;UserIsCourseAdmin=true&amp;UserIsPlatformAdmin=true" style="display:none">
+		<iframe id="content___Frame" src="/main/inc/lib/fckeditor/editor/fckeditor.html?InstanceName=content&amp;Toolbar=Messages" width="95%" height="250" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border: 0px; background-color: transparent; background-image: none; width: 95%; height: 250px;">
+		</iframe>
+		</div>
+	</div>
+';
+    echo '<input type="hidden" id="ticket_id" name="ticket_id" value="'.$_GET['ticket_id'].'">';
+	echo '<div class="row">
+		<div class="label">'.get_lang('FilesAttachment').'</div>
+		<div class="formw">
+				<span id="filepaths">
+				<div id="filepath_1">
+					<input type="file" name="attach_1" id="attach_1"  size="20" style="width:59%;"/>
+				</div></span>
+		</div>
+	</div>';
+	echo '<div class="row">
+		<div class="formw">
+			<span id="link-more-attach">
+				<a href="javascript://" onclick="return add_image_form()">'.get_lang('AddOneMoreFile').'</a></span>&nbsp;
+					('.sprintf(get_lang('MaximunFileSizeX'),format_file_size(api_get_setting('message_max_upload_filesize'))).')
+			</div>
+		</div>';
+	echo '<div class="row">
+		<div class="label"></div>
+		<div class="formw">	<button class="save" name="compose" type="submit">Enviar mensaje</button>'.($isAdmin?'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" name="confirmacion"/>Solicitar confirmaci&oacute;n':"").
+		'</div>
+	</div>';
+        echo '</form>';
+}
+Display::display_footer();
+?>

+ 101 - 0
plugin/ticket/s/tutor.php

@@ -0,0 +1,101 @@
+<?php
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+require_once 'tutor_report.lib.php';
+
+$htmlHeadXtra[] = '
+	<script type="text/javascript">
+$(document).ready(function (){
+    $(".ajax").live("click", function() {
+            var url     = this.href;
+            var dialog  = $("#dialog");
+            if ($("#dialog").length == 0) {
+                    dialog  = $("<div id=\"dialog\" style=\"display:hidden\"></div>").appendTo("body");
+            }
+
+            // load remote content
+            dialog.load(
+                            url,                    
+                            {},
+                            function(responseText, textStatus, XMLHttpRequest) {
+                                    dialog.dialog({
+                                            modal	: true, 
+                                            width	: 540, 
+                                            height	: 400        
+                                    });	                    
+            });
+            //prevent the browser to follow the link
+            return false;
+    });
+});	
+		
+		
+function mostrarContenido(div){
+	if($("div#"+div).attr("class")=="blackboard_hide"){
+		$("div#"+div).attr("class","blackboard_show");
+		$("div#"+div).attr("style","");
+	}else{
+		$("div#"+div).attr("class","blackboard_hide");
+		$("div#"+div).attr("style","");
+	}
+		
+}
+		
+function save() {
+	work_id = $("#work_id").val();
+	forum_id = $("#forum_id").val();
+	rs_id = $("#rs_id").val();
+	 $.ajax({
+		contentType: "application/x-www-form-urlencoded",
+		beforeSend: function(objeto) {
+		$("div#confirmacion").html("<img src=\'../../../main/inc/lib/javascript/indicator.gif\' />"); },
+		type: "POST",
+		url: "update_report.php",
+		data: "work_id="+work_id+"&forum_id="+forum_id+"&rs_id="+rs_id,
+		success: function(datos) {
+			$("div#confirmacion").html(datos);
+			 location.reload();
+		}
+	});
+}
+</script>
+<style>
+.blackboard_show {
+	float:left;
+	position:absolute;
+	border:1px solid black;
+	width: 350px;
+	background-color:white;
+	z-index:99; padding: 3px;
+	display: inline;
+}
+.blackboard_hide {
+	display: none;
+}
+.reportes{
+	border:1px ;	
+}
+.reportes th {
+    border-bottom: 1px solid #DDDDDD;
+    line-height: normal;
+    text-align: center;
+    vertical-align: middle;
+    background-color: #F2F2F2; 
+}
+</style>';
+
+$course_code = api_get_course_id();
+$resultado = inicializarReporte($course_code);
+if(isset($_GET['action'])){
+	Export::export_table_xls($resultado['exportar'],"REPORTE ALUMNOS CURSO".$course_code);
+}else{
+	Display::display_header();
+	api_protect_course_script();
+	if (!api_is_allowed_to_edit()){
+		api_not_allowed();
+	}
+	echo $resultado['mostrar'];
+	Display::display_footer();
+}
+?>

+ 190 - 0
plugin/ticket/s/tutor_report.lib.php

@@ -0,0 +1,190 @@
+<?php
+function inicializarReporte($course_code){
+	$course_info = api_get_course_info($course_code);
+	$table_reporte_semanas = Database::get_main_table('rp_reporte_semanas');
+	$table_students_report = Database::get_main_table('rp_students_report');
+	$table_semanas_curso = Database::get_main_table('rp_semanas_curso');
+	$table_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
+	$table_post = Database::get_course_table(TABLE_FORUM_POST, $course_info['dbName']);
+	$table_work = Database::get_course_table(TABLE_STUDENT_PUBLICATION, $course_info['dbName']);
+	$res = Database::query("SELECT COUNT(*) as cant FROM $table_reporte_semanas WHERE course_code = '".$course_code."'");
+	$sql_semanas = "SELECT semanas FROM $table_semanas_curso WHERE course_code = '$course_code'";
+	$res_semanas = Database::query($sql_semanas);
+	$semanas = Database::fetch_object($res_semanas);
+	$obj = Database::fetch_object($res);
+	$numero_semanas = (!isset($_POST['numerosemanas']))?(($semanas->semanas==0)?7:$semanas->semanas):$_POST['numerosemanas'];
+	Database::query("REPLACE INTO $table_semanas_curso (course_code , semanas) VALUES ('$course_code','$numero_semanas')");
+	if(intval($obj->cant) != $numero_semanas){
+		
+		if(intval($obj->cant) > $numero_semanas){
+			 $sql ="DELETE FROM $table_reporte_semanas WHERE  week_id > $numero_semanas AND course_code = '$course_code'";
+			 Database::query("DELETE FROM $table_reporte_semanas WHERE  week_id > $numero_semanas AND course_code = '$course_code'");
+		}else{
+			for ($i = $obj->cant+1 ; $i <= $numero_semanas ; $i++){
+				if(!Database::query("INSERT INTO $table_reporte_semanas (week_id,course_code,forum_id,work_id,quiz_id,pc_id)
+						VALUES ('$i','$course_code','0','0','0','0' )")){							
+						return false;
+				}
+			}
+		}		
+	}
+	
+	$sql = "REPLACE INTO $table_students_report (user_id,week_report_id, work_ok , thread_ok , quiz_ok , pc_ok)
+			SELECT cu.user_id, rs.id, 0, 0, 0, 0
+			FROM $table_course_rel_user cu
+			LEFT JOIN $table_reporte_semanas rs ON cu.course_code = rs.course_code
+			WHERE cu.status = '5' AND rs.course_code = '$course_code'
+			ORDER BY cu.user_id, rs.id";
+	if(!Database::query($sql)){
+		return false;
+	}else{
+		$pagina = (!isset($_GET['page']))?1:$_GET['page'];
+		Database::query("UPDATE $table_students_report sr SET sr.work_ok = 1
+		WHERE CONCAT (sr.user_id,',',sr.week_report_id)
+		IN (SELECT DISTINCT CONCAT(w.user_id,',',rs.id)
+		FROM $table_work w  JOIN $table_reporte_semanas rs ON w.parent_id = rs.work_id)");
+		Database::query("UPDATE $table_students_report sr SET sr.thread_ok = 1
+		WHERE CONCAT (sr.user_id,',',sr.week_report_id)
+		IN (SELECT DISTINCT CONCAT(f.poster_id,',',rs.id)
+		FROM $table_post f  JOIN $table_reporte_semanas rs ON f.thread_id = rs.forum_id)");
+		return mostrarResultados($course_info,$numero_semanas,$pagina);
+	}
+	
+}
+function mostrarResultados($course_info,$numero_semanas, $pagina){
+	$course_code = $course_info['code'];
+	$table_reporte_semanas = Database::get_main_table('rp_reporte_semanas');
+	$table_students_report = Database::get_main_table('rp_students_report');
+	$table_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
+	$table_user = Database::get_main_table(TABLE_MAIN_USER );
+	$table_thread = Database::get_course_table(TABLE_FORUM_THREAD, $course_info['dbName']);
+	$table_work = Database::get_course_table(TABLE_STUDENT_PUBLICATION, $course_info['dbName']);
+	
+	$resultados = array();
+	$table_export = array();
+	$sql_encabezado = "SELECT rs.id as id,rs.week_id, w.title AS work_title,  t.thread_title ,'EVALUACION' as eval_title ,'QUIZ' as pc_title
+						FROM $table_reporte_semanas rs
+						LEFT JOIN $table_thread t ON t.thread_id =  rs.forum_id
+						LEFT JOIN $table_work w ON w.id = rs.work_id
+						WHERE rs.course_code = '$course_code'
+						ORDER BY rs.week_id";
+	$result_encabezado = Database::query($sql_encabezado) ;
+	$ids = array();
+	$fila = '<tr>
+		<th ></th>';
+	$fila_export_encabezado = array(null,null);
+	$fila_export_encabezado2 = array(null,ull);
+	while ($rowe = Database::fetch_assoc($result_encabezado)){
+		$fila_export_encabezado[] =  utf8_decode('Tarea'.$rowe['week_id']);
+		$fila_export_encabezado[] =  utf8_decode('Foro'.$rowe['week_id']);
+		//$fila_export_encabezado[] =  utf8_decode('Eval'.$rowe['week_id']);
+		//$fila_export_encabezado[] =  utf8_decode('PC'.$rowe['week_id']);
+		$fila_export_encabezado2[] = utf8_decode($rowe['work_title']);
+		$fila_export_encabezado2[] = utf8_decode($rowe['thread_title']);
+		//$fila_export_encabezado2[] = utf8_decode($rowe['eval_title']);
+		//$fila_export_encabezado2[] = utf8_decode($rowe['pc_title']);
+		$fila_export = array('Tarea'.$rowe['week_id'],'Foro'.$rowe['week_id'],'Eval'.$rowe['week_id'],'PC'.$rowe['week_id']);
+		if ($rowe['week_id'] > (($pagina-1)*7) &&  $rowe['week_id'] <= (7*$pagina)){
+			$ids[$rowe['week_id']] = $rowe['id'];
+			$fila.='<th>
+				<a href="#" onClick="mostrarContenido('."'tarea".$rowe['week_id']."'".');">Tarea'.$rowe['week_id'].'
+						<div class="blackboard_hide" id="tarea'.$rowe['week_id'].'">'.$rowe['work_title'].'</div>
+				</a></th>';
+			$fila.= '<th>
+				<a href="#" onClick="mostrarContenido('."'foro".$rowe['week_id']."'".');">Foro'.$rowe['week_id'].'
+						<div class="blackboard_hide" id="foro'.$rowe['week_id'].'">'.$rowe['thread_title'].'</div>
+				</a>
+				</th>';
+			/*$fila.= '<th>
+				<a href="#" onClick="mostrarContenido('."'eval".$rowe['week_id']."'".');">Eval'.$rowe['week_id'].'
+					<div class="blackboard_hide" id="eval'.$rowe['week_id'].'">'.$rowe['eval_title'].'</div>
+				</a>
+				</th>';
+			$fila.= '<th>
+				<a href="#" onClick="mostrarContenido('."'pc".$rowe['week_id']."'".');">PC'.$rowe['week_id'].'
+					<div class="blackboard_hide" id="pc'.$rowe['week_id'].'">'.$rowe['pc_title'].'</div>
+				</a>
+				</th>';*/
+		}
+		
+	}
+	$table_export[] = $fila_export_encabezado;
+	$table_export[] = $fila_export_encabezado2;
+	$fila.=  '</tr>';
+	
+	$html = '<form action="tutor.php" name="semanas" id="semanas" method="POST">
+			<div class="row">
+			Seleccione cantidad de semanas: 
+			<select name="numerosemanas" id="numerosemanas" onChange="submit();">
+			<option value="7" '.(($numero_semanas ==7)?'selected="selected"':"").'>7 Semanas</option>
+			<option value="14" '.(($numero_semanas ==14)?'selected="selected"':"").'>14 Semanas</option>
+			</select>';
+	
+	
+	if($numero_semanas == 14) {
+		$html .= '<span style="float:right;"><a href="tutor.php?page='.(($pagina == 1)?2:1).'">'.(($pagina == 1)?"Siguiente":"Anterior").'</a></span>';		
+	}
+	$html .= '<span style="float:right;"><a href="'.api_get_self().'?action=export'.$get_parameter.$get_parameter2.'">'.Display::return_icon('import_excel.png',get_lang('Export'),'','32').'</a></span>';
+	
+	$html .=	'</form>';
+	$html .= '<table class="reportes">';
+	$html .= '<tr>
+			<th ></th>';
+	for ($i=(7*$pagina-6); $i <= $pagina*7;$i++){
+		$html .= '<th colspan="2">Semana '.$i.'<a href="assign_tickets.php?id='.$ids[$i].'" class="ajax">'.Display::return_icon('edit.png', get_lang('Edit'),  array('width'=>'16','height'=>'16'), 22).'</a></th>';
+	}
+	$html .=  '</tr>';
+	$html .= $fila;
+	$sql = "SELECT u.username , u.user_id , CONCAT(u.lastname,' ', u.firstname ) as fullname , rs.week_id , sr.work_ok ,sr.thread_ok , sr.quiz_ok , sr.pc_ok , rs.course_code
+			FROM $table_students_report sr
+			JOIN $table_reporte_semanas rs ON sr.week_report_id = rs.id
+			JOIN $table_user u ON u.user_id = sr.user_id
+			WHERE rs.course_code = '$course_code'
+			ORDER BY u.lastname , u.username , rs.week_id
+	";
+	$result = Database::query($sql);
+	while ($row = Database::fetch_assoc($result)){
+		$resultadose[$row['username']][$row['week_id']] = $row;
+		if ($row['week_id'] > (($pagina-1)*7) &&  $row['week_id'] <= (7*$pagina) ){
+			$resultados[$row['username']][$row['week_id']] = $row;
+			if(count($resultados[$row['username']]) == 7 ){
+				$html.= mostrarResultadoAlumno($resultados[$row['username']],$pagina);
+			}
+		}
+		if(count($resultadose[$row['username']]) == $numero_semanas ){
+				$table_export[] = mostrarResultadoAlumnoExportar($resultadose[$row['username']],$numero_semanas);
+		}
+	}
+	$html .= '
+		  </table>';
+	return array('mostrar'=>$html,'exportar'=>$table_export);
+}
+function mostrarResultadoAlumno($datos,$pagina){
+	$inicio = (7*$pagina-6);
+	$fila = '<tr>';
+	
+	$fila.= '<td><a href="'.api_get_path(WEB_CODE_PATH).'user/userInfo.php?'.api_get_cidreq().'&uInfo='.$datos[$inicio]['user_id'].'">'.$datos[$inicio]['username'].'</a></td>';
+	foreach ($datos as $dato){
+			$fila.= '<td align="center">'.(($dato['work_ok']==1)?Display::return_icon('check.png'):Display::return_icon('aspa.png')).'</td>';
+			$fila.= '<td align="center">'.(($dato['thread_ok']==1)?Display::return_icon('check.png'):Display::return_icon('aspa.png')).'</td>';
+			//$fila.= '<td>'.(($dato['quiz_ok']==1)?Display::return_icon('check.png'):Display::return_icon('aspa.png')).'</td>';
+			//$fila.= '<td>'.(($dato['pc_ok']==1)?Display::return_icon('check.png'):Display::return_icon('aspa.png')).'</td>';
+	}
+	$fila.= '</tr>';	
+	return $fila;
+}
+function mostrarResultadoAlumnoExportar($datos ,$numero_semanas){
+	$fila = array();
+	$fila[] = utf8_decode($datos[1]['username']);
+	$fila[]=  utf8_decode($datos[1]['fullname']);
+	foreach ($datos as $dato){
+		//if ($datos['week_id'] < $numero_semanas){
+			$fila[]= ($dato['work_ok']==1)?"SI":"NO";
+			$fila[]= ($dato['thread_ok']==1)?"SI":"NO";
+			//$fila[]= ($dato['quiz_ok']==1)?"SI":"NO";
+			//$fila[]= ($dato['pc_ok']==1)?"SI":"NO";
+		//}
+	}
+	return $fila;
+}
+?>

+ 16 - 0
plugin/ticket/s/update_report.php

@@ -0,0 +1,16 @@
+<?php
+require_once '../config.php';
+$plugin = TicketPlugin::create();
+
+$work_id = $_POST['work_id'];
+$forum_id = $_POST['forum_id'];
+$rs_id = $_POST['rs_id'];
+api_protect_course_script();
+if (!api_is_allowed_to_edit()){
+	Display::display_error_message($plugin->get_lang("DeniedAccess"));
+}else{
+	$sql ="UPDATE ".Database::get_main_table('rp_reporte_semanas')." SET work_id = '$work_id' , forum_id = '$forum_id' WHERE  id ='$rs_id'";
+	Database::query($sql);
+	Display::display_confirmation_message("Se actualizo con exito");
+}
+?>

+ 55 - 0
plugin/ticket/start.php

@@ -0,0 +1,55 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * This script initiates a ticket management system session
+ * @package chamilo.plugin.ticket
+ */
+/**
+ * Initialization
+ */
+$course_plugin = 'ticket'; //needed in order to load the plugin lang variables
+require_once dirname(__FILE__).'/config.php';
+$tool_name = get_lang('Ticket');
+$tpl = new Template($tool_name);
+$bbb = new bbb();
+
+if ($bbb->plugin_enabled) {
+    if ($bbb->is_server_running()) {
+        if (isset($_GET['launch']) && $_GET['launch'] == 1) {
+            $meeting_params = array();
+            $meeting_params['meeting_name'] = api_get_course_id();
+
+            if ($bbb->meeting_exists($meeting_params['meeting_name'])) {
+                $url = $bbb->join_meeting($meeting_params['meeting_name']);
+                if ($url) {
+                    header('location: '.$url);
+                    exit;
+                } else {
+                    $url = $bbb->create_meeting($meeting_params);
+                    header('location: '.$url);
+                    exit;
+                }
+            } else {
+                if ($bbb->is_teacher()) {
+                    $url = $bbb->create_meeting($meeting_params);
+                    header('location: '.$url);
+                    exit;
+                } else {
+                    $url = 'listing.php';
+                    header('location: '.$url);
+                    exit;
+                }
+            }
+        } else {
+            $url = 'listing.php';
+            header('location: '.$url);
+            exit;
+        }
+    } else {
+        $message = Display::return_message(get_lang('ServerIsNotRunning'), 'warning');
+    }
+} else {
+    $message = Display::return_message(get_lang('ServerIsNotConfigured'), 'warning');
+}
+$tpl->assign('message', $message);
+$tpl->display_one_col_template();

+ 13 - 0
plugin/ticket/uninstall.php

@@ -0,0 +1,13 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * This script is included by main/admin/settings.lib.php when unselecting a plugin
+ * and is meant to remove things installed by the install.php script in both
+ * the global database and the courses tables
+ * @package chamilo.plugin.bigbluebutton
+ */
+/**
+ * Queries
+ */
+require_once dirname(__FILE__).'/config.php';
+TicketPlugin::create()->uninstall();