Julio Montoya 14 years ago
parent
commit
c7b8322e6f

+ 65 - 64
documentation/changelog.html

@@ -5,12 +5,12 @@
   <title>Chamilo Changelog</title><link rel="stylesheet" href="default.css" type="text/css" media="screen,projection" />
   <link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
   <style type="text/css">
-	<!--
-		@page { size: 21cm 29.7cm; margin: 2cm }
-		pre { font-family: "Courier New", monospace }
-		p { margin-bottom: 0.21cm }
-		.code {margin: 1em 1em 1em 2em; padding: 0.5em; background-color: rgb(229, 229, 229); vertical-align: top; border: 1px solid #999999;}
-	--></style></head>
+    <!--
+        @page { size: 21cm 29.7cm; margin: 2cm }
+        pre { font-family: "Courier New", monospace }
+        p { margin-bottom: 0.21cm }
+        .code {margin: 1em 1em 1em 2em; padding: 0.5em; background-color: rgb(229, 229, 229); vertical-align: top; border: 1px solid #999999;}
+    --></style></head>
 <body>
 <div id="header1">
 <h1>Chamilo&nbsp;Changelog</h1>
@@ -32,6 +32,7 @@
    <li>Learning Path: New LP exercises reports added for teachers and admins (Feature BT#1634)</li>
    <li><span id="result_box" lang="en" xml:lang="en"><span title="">New tool to create, edit and import vectorial images, and export to png images</span></span> (Feature # 2044)</li>
    <li>The documents tool and the learn path tool can display vectorial images</li>
+   <li>An optional "Course (training) validation" feature has been implemented. When it is activated, teachers loose ability to create coursers. Teachers fill course requests instead. Then, after approval, the requested courses are created by the platform administrator. (Feature # 2099)</li>
 </ul>
 <h3>Debugging</h3>
 <ul>
@@ -39,7 +40,7 @@
   <li>Added more quality at the icons</li>
   <li>Fixed an encoding problem about database connection which is specific to Chinese language. The initial solution has been proposed by Oliver Corre (Bug #1802)</li>
   <li>Attendance: Adding sticky header for the attendance sheet BT#</li>
-  <li>Multiple URL feature: Fixed Course user list (BT#1547) </li>  
+  <li>Multiple URL feature: Fixed Course user list (BT#1547) </li>
   <li>Multiple URL feature: Fixed User List options when adding courses, users, sessions see BT#1470 </li>
   <li>Multiple URL feature: System Announcements and Global agenda now are filtered by URL see BT#1441</li>
   <li>Multiple URL feature: Added multiple URL support when adding user, courses, sessions to a Human Resources see BT#1470 </li>
@@ -51,8 +52,8 @@
   <li>Exercises: Question order in results fixed #2073</li>
   <li>Exercises: Fixing question list order #2075</li>
   <li>Exercises: Allowing duplicate an exercise within a session BT#1647</li>
-  <li>Documents: Fixing coach and students in a session permissions BT#1652</li>    
-  <li>Learning Path: Teachers can reset LP results see #2024</li>    
+  <li>Documents: Fixing coach and students in a session permissions BT#1652</li>
+  <li>Learning Path: Teachers can reset LP results see #2024</li>
   <li>Profile: Deleting production user's files fixed see #1682</li>
   <li>Installation: Tracking will be always enabled #2066</li>
   <li>Thickbox does not work well in the Social Tool  #1995</li>
@@ -62,7 +63,7 @@
   <li>Fixed bug deleting course teacher in admin edition #2109</li>
   <li>Gradebook: Hiding print icon in Certificates BT#1650</li>
   <li>Link Tool: IE icons replaced</li>
-  
+
 </ul>
 <h3>Security</h3>
 <ul>
@@ -228,7 +229,7 @@
   <li>Quiz tool: Fixed problem with open questions when entering words with the "rn" characters see CT#1035 </li>
   <li>Quiz tool + LP : Fixed bug when adding a exercise twice in the same LP with multiple attempts or not.</li>
   <li>Quiz tool + LP + Multiple attempts : Pre requisites will work the first time a student pass the LP.
- 	  If a student finished all steps correctly he will view all steps, prerequisites will not work here.</li>
+       If a student finished all steps correctly he will view all steps, prerequisites will not work here.</li>
   <li>Learning Path (Courses): PHP sessions of a LP are destroyed when visiting the main course page.</li>
   <li>Assignment tool: Work.php deletes all homeworks bugs fixed. Reported and fixed by carlosbrolotobar <a href="http://www.chamilo.org/node/143" target="_blank">http://www.chamilo.org/node/143</a></li>
   <li>Core API: Support has been implemented for json_encode() function for PHP version &#60; 5.2. The correspondent bug-report "Hide and show not working" and testing have been done by Hubert Borderiou <a href="http://support.chamilo.org/issues/761" target="_blank">http://support.chamilo.org/issues/761</a></li>
@@ -648,28 +649,28 @@ if you are willing to keep that change.</li>
 <h3>New Features</h3>
 
 <ul>
-	<li>Considerable security improvements - 2 major and 1 minor security patches have been applied since the latest stable version</li>
-	<li>SCORM
+    <li>Considerable security improvements - 2 major and 1 minor security patches have been applied since the latest stable version</li>
+    <li>SCORM
 export improvement (now generates SCORM 1.2 compliant packages and
 transforms Dokeos quizzes into SCO items, using interactions as a bonus)</li>
-	<li>Possibility to filter extension of submitted files all around Dokeos</li>
-	<li>OpenID authentication support</li>
-	<li>Possibility to import Word documents</li>
-	<li>Possibility to import docx and pptx documents (new MS-Office format)</li>
-	<li>Grades,
+    <li>Possibility to filter extension of submitted files all around Dokeos</li>
+    <li>OpenID authentication support</li>
+    <li>Possibility to import Word documents</li>
+    <li>Possibility to import docx and pptx documents (new MS-Office format)</li>
+    <li>Grades,
 evaluations and success certificates available thanks to the
 integration of the gradebook extension. Activating this module will
 clash with a gradebook extension installation made previously</li>
-	<li>Coloured icons added to courses list in administration panel to show access permissions</li>
-	<li>Logout button now shows the username of the current user</li>
-	<li>Student view re-activated and fully-functional</li>
-	<li>Searching
+    <li>Coloured icons added to courses list in administration panel to show access permissions</li>
+    <li>Logout button now shows the username of the current user</li>
+    <li>Student view re-activated and fully-functional</li>
+    <li>Searching
 the forum is now possible so you can use the forum as a knowledge base.
 The search results are highlighted throughout the forum and you can
 search on multiple words also. </li>
     <li>Group members are now displayed in a sortable table</li>
-	<li>Possibility to export survey results in XLS format</li>
-	<li>Documents, Works and Dropbox tools usability has been improved in many ways</li>
+    <li>Possibility to export survey results in XLS format</li>
+    <li>Documents, Works and Dropbox tools usability has been improved in many ways</li>
     <li>In the agenda, you can display the X upcoming events (can be configured by the platform admin)</li>
     <li>The course agenda now has a month view like the my agenda</li>
     <li>In
@@ -677,25 +678,25 @@ the user list of the platform administration you can now quickly see
 for what courses the user is subscribed by hovering over the courses
 icon</li>
     <li>The platform system announcements can now be sent through email also</li>
-	<li>User
+    <li>User
 fields have been added globally, allowing you to add user data like
 birthdate, mother tongue, city or whatever data you want to ask your
 users</li>
-	<li>LDAP
-		<ul>
-			<li>The LDAP code has changed. If you had some customisations there, you might want to save them and re-apply them after the upgrade</li>
-			<li>Functions renamed to respect coding conventions and use ldap_ namespace</li>
-			<li>Most
+    <li>LDAP
+        <ul>
+            <li>The LDAP code has changed. If you had some customisations there, you might want to save them and re-apply them after the upgrade</li>
+            <li>Functions renamed to respect coding conventions and use ldap_ namespace</li>
+            <li>Most
 parameters moved to the administration panel. You will need to
 configure the administration panel with the settings that were
 previously in ldap_var.inc.php</li>
-			<li>Added non-anonymous mode (just add a login and a password in the configuration panel)</li>
-			<li>Added search domain configuration through panel</li>
-			<li>Added customizable field-check for student-teacher switch</li>
-			<li>The installation guide has been updated to help you find your way through the new LDAP configuration panel</li>
-			<li>You still need to activate LDAP by uncommenting two lines in configuration.php</li>
-	    </ul>
-	</li>
+            <li>Added non-anonymous mode (just add a login and a password in the configuration panel)</li>
+            <li>Added search domain configuration through panel</li>
+            <li>Added customizable field-check for student-teacher switch</li>
+            <li>The installation guide has been updated to help you find your way through the new LDAP configuration panel</li>
+            <li>You still need to activate LDAP by uncommenting two lines in configuration.php</li>
+        </ul>
+    </li>
     <li>New stylesheets can be added through the platform administration interface</li>
     <li>Notification
 by email has been improved in the forum. You can now indicate that you
@@ -712,45 +713,45 @@ settings.</li>
     <li>Group forum is also displayed in the group space</li>
     <li>Surveys that are not based on invitation but open to all (or certain) members of the course are now available</li>
     <li>Agenda
-    	<ul>
-    		<li>iCal import and export of course events, with a choice of public, private or confidential markers</li>
-    		<li>Repetitive
+        <ul>
+            <li>iCal import and export of course events, with a choice of public, private or confidential markers</li>
+            <li>Repetitive
 course events can be created (and exported to iCal). Repetitions types
 supported are: daily, weekly, monthly by date (e.g. the 5th of each
 month) and yearly by date</li>
-   		</ul>
-	</li>
-	<li>Document templates have been greatly improved to speed-up custom course content creation</li>
-	<li>Audiorecorder
+           </ul>
+    </li>
+    <li>Document templates have been greatly improved to speed-up custom course content creation</li>
+    <li>Audiorecorder
 (depending on streaming server) now records sounds in the
 document/audio directory, making them easily reusable by the course
 admin</li>
-	<li>Audiorecorder is not loaded by default (took too long) and you can load it with a simple click</li>
-	<li>W3C - Compliance with XHTML 1.0 Transitional has been improved</li>
-	<li>Tracking - A new page to display access details by user is available under the Reporting tab, in the user details in a course</li>
-	<li>Removed header from learning path tool. It was taking too much space and was not flexible enough for CSS styling</li>
-	<li>Improved speed of 1.6 to 1.8 migration by adding indexes</li>
+    <li>Audiorecorder is not loaded by default (took too long) and you can load it with a simple click</li>
+    <li>W3C - Compliance with XHTML 1.0 Transitional has been improved</li>
+    <li>Tracking - A new page to display access details by user is available under the Reporting tab, in the user details in a course</li>
+    <li>Removed header from learning path tool. It was taking too much space and was not flexible enough for CSS styling</li>
+    <li>Improved speed of 1.6 to 1.8 migration by adding indexes</li>
     </ul>
 <br />
 <h3>Debugging</h3>
 <ul>
-	<li>Prerequisites management in learning paths fixed (includes quizzes, hotpotatoes and SCORM)</li>
-	<li>Various minor bugs fixed in the learning path tool (scoring, copy, re-ordering)</li>
-	<li>Various minor bugs fixed in the session handling</li>
-	<li>Fixes to the survey tool (date management, questions order in export)</li>
-	<li>Fixes to the calendar tool (access by students)</li>
-	<li>Fixes to the announcement tool (access by students)</li>
-	<li>Fixes to the group tool (default group settings)</li>
-	<li>Bugfix: complete export in survey tool displayed the question of all the surveys and not only those of the selected survey</li>
+    <li>Prerequisites management in learning paths fixed (includes quizzes, hotpotatoes and SCORM)</li>
+    <li>Various minor bugs fixed in the learning path tool (scoring, copy, re-ordering)</li>
+    <li>Various minor bugs fixed in the session handling</li>
+    <li>Fixes to the survey tool (date management, questions order in export)</li>
+    <li>Fixes to the calendar tool (access by students)</li>
+    <li>Fixes to the announcement tool (access by students)</li>
+    <li>Fixes to the group tool (default group settings)</li>
+    <li>Bugfix: complete export in survey tool displayed the question of all the surveys and not only those of the selected survey</li>
     <li>Bugfix:
 registering a new user resulted in the language field of the user being
 empty which resulted in an english profile by default. This has now
 been changed to the platform language. </li>
     <li>Performance improvement in the user list of the platform administration </li>
-	<li>Bugfix: group tutors were not migrated from 1.6 to 1.8</li>
-	<li>SCORM export: fixes in export method</li>
-	<li>Documentation is now fully XHTML 1.0 Transitional compliant</li>
-	<li>Fix FCKeditor Flash upload lack of usability and problems with IE</li>
+    <li>Bugfix: group tutors were not migrated from 1.6 to 1.8</li>
+    <li>SCORM export: fixes in export method</li>
+    <li>Documentation is now fully XHTML 1.0 Transitional compliant</li>
+    <li>Fix FCKeditor Flash upload lack of usability and problems with IE</li>
 </ul>
 <br />
 <h3>Known issues</h3>
@@ -1176,7 +1177,7 @@ a simple videoconferencing interface.</p>
 </div>
 <hr />
     <a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10-blue" alt="Valid XHTML 1.0 Transitional" style="margin: 1em; float: right;" height="31" width="88" /></a>
-	<a href="http://jigsaw.w3.org/css-validator/">
-		<img src="http://jigsaw.w3.org/css-validator/images/vcss-blue" style="margin: 1em; float: right;" alt="Valid CSS" />
-	</a>
+    <a href="http://jigsaw.w3.org/css-validator/">
+        <img src="http://jigsaw.w3.org/css-validator/images/vcss-blue" style="margin: 1em; float: right;" alt="Valid CSS" />
+    </a>
 </body></html>

+ 15 - 9
documentation/credits.html

@@ -5,12 +5,12 @@
   <title>Chamilo Credits</title><link rel="stylesheet" href="default.css" type="text/css" media="screen,projection" />
   <link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
   <style type="text/css">
-	<!--
-		@page { size: 21cm 29.7cm; margin: 2cm }
-		pre { font-family: "Courier New", monospace }
-		p { margin-bottom: 0.21cm }
-		.code {margin: 1em 1em 1em 2em; padding: 0.5em; background-color: rgb(229, 229, 229); vertical-align: top; border: 1px solid #999999;}
-	--></style></head>
+    <!--
+        @page { size: 21cm 29.7cm; margin: 2cm }
+        pre { font-family: "Courier New", monospace }
+        p { margin-bottom: 0.21cm }
+        .code {margin: 1em 1em 1em 2em; padding: 0.5em; background-color: rgb(229, 229, 229); vertical-align: top; border: 1px solid #999999;}
+    --></style></head>
 
 <body>
 <div id="header1">
@@ -138,6 +138,12 @@ rewritten by
   <li>Roan Embrechts  (roan.embrechts@vub.ac.be)</li>
 </ul>
 
+<h2>Course validation optional feature</h2>
+<ul>
+  <li>José Manuel Abuin Mosquera <chema@cesga.es>, 2010, Centro de Supercomputacion de Galicia (CESGA)</li>
+  <li>Bruno Rubio Gayo <brubio@cesga.es>, 2010, CESGA</li>
+  <li>Ivan Tcholakov <ivantcholakov@gmail.com> (technical adaptation for Chamilo 1.8.8), 2010</li>
+</ul>
 
 <h2>Chat</h2>
 <ul>
@@ -525,7 +531,7 @@ of information requests and organizing great community events</li>
 <br />
 <hr />
     <a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10-blue" alt="Valid XHTML 1.0 Transitional" style="margin: 1em; float: right;" height="31" width="88" /></a>
-	<a href="http://jigsaw.w3.org/css-validator/">
-		<img src="http://jigsaw.w3.org/css-validator/images/vcss-blue" style="margin: 1em; float: right;" alt="Valid CSS" />
-	</a>
+    <a href="http://jigsaw.w3.org/css-validator/">
+        <img src="http://jigsaw.w3.org/css-validator/images/vcss-blue" style="margin: 1em; float: right;" alt="Valid CSS" />
+    </a>
 </body></html>

+ 20 - 4
main/admin/course_request_accepted.php

@@ -44,6 +44,7 @@ $course_validation_feature = api_get_setting('course_validation') == 'true';
 $delete_course_request = intval($_GET['delete_course_request']);
 $message = trim(Security::remove_XSS(stripslashes(urldecode($_GET['message']))));
 $is_error_message = !empty($_GET['is_error_message']);
+$keyword = Database::escape_string(trim($_GET['keyword']));
 
 if ($course_validation_feature) {
 
@@ -101,6 +102,8 @@ function get_number_of_requests() {
  * Get course data to display
  */
 function get_request_data($from, $number_of_items, $column, $direction) {
+    global $keyword;
+
     $course_request_table = Database :: get_main_table(TABLE_MAIN_COURSE_REQUEST);
     $users_table = Database :: get_main_table(TABLE_MAIN_USER);
     $course_users_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
@@ -114,6 +117,9 @@ function get_request_data($from, $number_of_items, $column, $direction) {
                    id  AS col6
                    FROM $course_request_table WHERE status = ".COURSE_REQUEST_ACCEPTED;
 
+    if ($keyword != '') {
+        $sql .= " AND (title LIKE '%".$keyword."%' OR code LIKE '%".$keyword."%' OR visual_code LIKE '%".$keyword."%')";
+    }
     $sql .= " ORDER BY col$column $direction ";
     $sql .= " LIMIT $from,$number_of_items";
     $res = Database :: query($sql);
@@ -155,15 +161,25 @@ if (!$course_validation_feature) {
     exit;
 }
 
+// Create a simple search-box.
+$form = new FormValidator('search_simple', 'get', '', '', 'width=200px', false);
+$renderer = $form->defaultRenderer();
+$renderer->setElementTemplate('<span>{element}</span> ');
+$form->addElement('text', 'keyword', get_lang('keyword'));
+$form->addElement('style_submit_button', 'submit', get_lang('Search'), 'class="search"');
+
 // The action bar.
-echo '<div class="actions">';
+echo '<div style="float: right; margin-top: 5px; margin-right: 5px;">';
 echo '<a href="course_list.php">'.Display::return_icon('courses.gif', get_lang('CourseList')).get_lang('CourseList').'</a>';
-echo '<a href="course_request_review.php">'.Display::return_icon('course_request_pending.png', get_lang('ReviewCourseRequests')).get_lang('ReviewCourseRequests').'</a>';
-echo '<a href="course_request_rejected.php">'.Display::return_icon('course_request_rejected.gif', get_lang('RejectedCourseRequests')).get_lang('RejectedCourseRequests').'</a>';
+echo ' <a href="course_request_review.php">'.Display::return_icon('course_request_pending.png', get_lang('ReviewCourseRequests')).get_lang('ReviewCourseRequests').'</a>';
+echo ' <a href="course_request_rejected.php">'.Display::return_icon('course_request_rejected.gif', get_lang('RejectedCourseRequests')).get_lang('RejectedCourseRequests').'</a>';
+echo '</div>';
+echo '<div class="actions">';
+$form->display();
 echo '</div>';
 
 // Create a sortable table with the course data.
-$table = new SortableTable('course_requests', 'get_number_of_requests', 'get_request_data', 2);
+$table = new SortableTable('course_requests_accepted', 'get_number_of_requests', 'get_request_data', 5, 20, 'DESC');
 $table->set_additional_parameters($parameters);
 $table->set_header(0, '', false);
 $table->set_header(1, get_lang('Code'));

+ 14 - 8
main/admin/course_request_edit.php

@@ -59,14 +59,13 @@ if ($course_validation_feature) {
         // Build the form.
         $form = new FormValidator('add_course', 'post', 'course_request_edit.php?id='.$id.'&caller='.$caller);
 
-        // TODO: Check which fields are to be mandatory.
-
         // Form title.
         $form->addElement('header', '', $tool_name);
 
         // Title.
         $form->addElement('text', 'title', get_lang('CourseName'), array('size' => '60', 'id' => 'title'));
         $form->applyFilter('title', 'html_filter');
+        $form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
 
         // Course category.
         $categories_select = $form->addElement('select', 'category_code', get_lang('Fac'), array());
@@ -77,6 +76,7 @@ if ($course_validation_feature) {
         $form->add_textfield('wanted_code', get_lang('Code'), false, array('size' => '$maxlength', 'maxlength' => $maxlength));
         $form->applyFilter('wanted_code', 'html_filter');
         $form->addRule('wanted_code', get_lang('Max'), 'maxlength', $maxlength);
+        $form->addRule('wanted_code', get_lang('ThisFieldIsRequired'), 'required');
 
         // The teacher.
         $titular = & $form->add_textfield('tutor_name', get_lang('Professor'), null, array('size' => '60', 'disabled' => 'disabled'));
@@ -84,15 +84,15 @@ if ($course_validation_feature) {
 
         // Description of the requested course.
         $form->addElement('textarea', 'description', get_lang('Description'), array('style' => 'border:#A5ACB2 solid 1px; font-family:arial,verdana,helvetica,sans-serif; font-size:12px', 'rows' => '3', 'cols' => '116'));
-        $form->addRule('description', get_lang('ThisFieldIsRequired'), 'required', '', '');
+        $form->addRule('description', get_lang('ThisFieldIsRequired'), 'required');
 
         // Objectives of the requested course.
         $form->addElement('textarea', 'objetives', get_lang('Objectives'), array('style' => 'border:#A5ACB2 solid 1px; font-family:arial,verdana,helvetica,sans-serif; font-size:12px', 'rows' => '3', 'cols' => '116'));
-        $form->addRule('objetives', get_lang('ThisFieldIsRequired'), 'required', '', '');
+        $form->addRule('objetives', get_lang('ThisFieldIsRequired'), 'required');
 
         // Target audience of the requested course.
         $form->addElement('textarea', 'target_audience', get_lang('TargetAudience'), array('style' => 'border:#A5ACB2 solid 1px; font-family:arial,verdana,helvetica,sans-serif; font-size:12px', 'rows' => '3', 'cols' => '116'));
-        $form->addRule('target_audience', get_lang('ThisFieldIsRequired'), 'required', '', '');
+        $form->addRule('target_audience', get_lang('ThisFieldIsRequired'), 'required');
 
         // Course language.
         $form->addElement('select_language', 'course_language', get_lang('Ln'));
@@ -100,9 +100,15 @@ if ($course_validation_feature) {
 
         // Submit buttons.
         $submit_buttons[] = FormValidator::createElement('style_submit_button', 'save_button', get_lang('Save'), array('class' => 'save'));
-        $submit_buttons[] = FormValidator::createElement('style_submit_button', 'accept_button', get_lang('Accept'), array('class' => 'save', 'style' => 'background-image: url('.api_get_path(WEB_IMG_PATH).'action_accept.gif);'));
-        $submit_buttons[] = FormValidator::createElement('style_submit_button', 'reject_button', get_lang('Reject'), array('class' => 'save', 'style' => 'background-image: url('.api_get_path(WEB_IMG_PATH).'action_reject.gif);'));
-        $submit_buttons[] = FormValidator::createElement('style_submit_button', 'ask_info_button', get_lang('AskAdditionalInfo'), array('class' => 'save', 'style' => 'background-image: url('.api_get_path(WEB_IMG_PATH).'request_info.gif);'));
+        if ($course_request_info['status'] != COURSE_REQUEST_ACCEPTED) {
+            $submit_buttons[] = FormValidator::createElement('style_submit_button', 'accept_button', get_lang('Accept'), array('class' => 'save', 'style' => 'background-image: url('.api_get_path(WEB_IMG_PATH).'action_accept.gif);'));
+        }
+        if ($course_request_info['status'] != COURSE_REQUEST_ACCEPTED && $course_request_info['status'] != COURSE_REQUEST_REJECTED) {
+            $submit_buttons[] = FormValidator::createElement('style_submit_button', 'reject_button', get_lang('Reject'), array('class' => 'save', 'style' => 'background-image: url('.api_get_path(WEB_IMG_PATH).'action_reject.gif);'));
+        }
+        if ($course_request_info['status'] != COURSE_REQUEST_ACCEPTED && intval($course_request_info['info']) <= 0) {
+            $submit_buttons[] = FormValidator::createElement('style_submit_button', 'ask_info_button', get_lang('AskAdditionalInfo'), array('class' => 'save', 'style' => 'background-image: url('.api_get_path(WEB_IMG_PATH).'request_info.gif);'));
+        }
         $form->addGroup($submit_buttons);
 
         // Hidden form fields.

+ 20 - 4
main/admin/course_request_rejected.php

@@ -47,6 +47,7 @@ $delete_course_request = intval($_GET['delete_course_request']);
 $request_info = intval($_GET['request_info']);
 $message = trim(Security::remove_XSS(stripslashes(urldecode($_GET['message']))));
 $is_error_message = !empty($_GET['is_error_message']);
+$keyword = Database::escape_string(trim($_GET['keyword']));
 
 if ($course_validation_feature) {
 
@@ -135,6 +136,8 @@ function get_number_of_requests() {
  * Get course data to display
  */
 function get_request_data($from, $number_of_items, $column, $direction) {
+    global $keyword;
+
     $course_request_table = Database :: get_main_table(TABLE_MAIN_COURSE_REQUEST);
     $users_table = Database :: get_main_table(TABLE_MAIN_USER);
     $course_users_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
@@ -148,6 +151,9 @@ function get_request_data($from, $number_of_items, $column, $direction) {
                    id  AS col6
                    FROM $course_request_table WHERE status = ".COURSE_REQUEST_REJECTED;
 
+    if ($keyword != '') {
+        $sql .= " AND (title LIKE '%".$keyword."%' OR code LIKE '%".$keyword."%' OR visual_code LIKE '%".$keyword."%')";
+    }
     $sql .= " ORDER BY col$column $direction ";
     $sql .= " LIMIT $from,$number_of_items";
     $res = Database :: query($sql);
@@ -194,15 +200,25 @@ if (!$course_validation_feature) {
     exit;
 }
 
+// Create a simple search-box.
+$form = new FormValidator('search_simple', 'get', '', '', 'width=200px', false);
+$renderer = $form->defaultRenderer();
+$renderer->setElementTemplate('<span>{element}</span> ');
+$form->addElement('text', 'keyword', get_lang('keyword'));
+$form->addElement('style_submit_button', 'submit', get_lang('Search'), 'class="search"');
+
 // The action bar.
-echo '<div class="actions">';
+echo '<div style="float: right; margin-top: 5px; margin-right: 5px;">';
 echo '<a href="course_list.php">'.Display::return_icon('courses.gif', get_lang('CourseList')).get_lang('CourseList').'</a>';
-echo '<a href="course_request_review.php">'.Display::return_icon('course_request_pending.png', get_lang('ReviewCourseRequests')).get_lang('ReviewCourseRequests').'</a>';
-echo '<a href="course_request_accepted.php">'.Display::return_icon('course_request_accepted.gif', get_lang('AcceptedCourseRequests')).get_lang('AcceptedCourseRequests').'</a>';
+echo ' <a href="course_request_review.php">'.Display::return_icon('course_request_pending.png', get_lang('ReviewCourseRequests')).get_lang('ReviewCourseRequests').'</a>';
+echo ' <a href="course_request_accepted.php">'.Display::return_icon('course_request_accepted.gif', get_lang('AcceptedCourseRequests')).get_lang('AcceptedCourseRequests').'</a>';
+echo '</div>';
+echo '<div class="actions">';
+$form->display();
 echo '</div>';
 
 // Create a sortable table with the course data.
-$table = new SortableTable('course_requests', 'get_number_of_requests', 'get_request_data', 2);
+$table = new SortableTable('course_requests_rejected', 'get_number_of_requests', 'get_request_data', 5, 20, 'DESC');
 $table->set_additional_parameters($parameters);
 $table->set_header(0, '', false);
 $table->set_header(1, get_lang('Code'));

+ 20 - 4
main/admin/course_request_review.php

@@ -50,6 +50,7 @@ $request_info = intval($_GET['request_info']);
 $delete_course_request = intval($_GET['delete_course_request']);
 $message = trim(Security::remove_XSS(stripslashes(urldecode($_GET['message']))));
 $is_error_message = !empty($_GET['is_error_message']);
+$keyword = Database::escape_string(trim($_GET['keyword']));
 
 if ($course_validation_feature) {
 
@@ -153,6 +154,8 @@ function get_number_of_requests() {
  * Get course data to display
  */
 function get_request_data($from, $number_of_items, $column, $direction) {
+    global $keyword;
+
     $course_request_table = Database :: get_main_table(TABLE_MAIN_COURSE_REQUEST);
     $users_table = Database :: get_main_table(TABLE_MAIN_USER);
     $course_users_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
@@ -177,6 +180,9 @@ function get_request_data($from, $number_of_items, $column, $direction) {
                    FROM $course_request_table WHERE status = ".COURSE_REQUEST_PENDING;
     }
 
+    if ($keyword != '') {
+        $sql .= " AND (title LIKE '%".$keyword."%' OR code LIKE '%".$keyword."%' OR visual_code LIKE '%".$keyword."%')";
+    }
     $sql .= " ORDER BY col$column $direction ";
     $sql .= " LIMIT $from,$number_of_items";
     $res = Database::query($sql);
@@ -239,16 +245,26 @@ if (!$course_validation_feature) {
     exit;
 }
 
+// Create a simple search-box.
+$form = new FormValidator('search_simple', 'get', '', '', 'width=200px', false);
+$renderer = $form->defaultRenderer();
+$renderer->setElementTemplate('<span>{element}</span> ');
+$form->addElement('text', 'keyword', get_lang('keyword'));
+$form->addElement('style_submit_button', 'submit', get_lang('Search'), 'class="search"');
+
 // The action bar.
-echo '<div class="actions">';
+echo '<div style="float: right; margin-top: 5px; margin-right: 5px;">';
 echo '<a href="course_list.php">'.Display::return_icon('courses.gif', get_lang('CourseList')).get_lang('CourseList').'</a>';
-echo '<a href="course_request_accepted.php">'.Display::return_icon('course_request_accepted.gif', get_lang('AcceptedCourseRequests')).get_lang('AcceptedCourseRequests').'</a>';
-echo '<a href="course_request_rejected.php">'.Display::return_icon('course_request_rejected.gif', get_lang('RejectedCourseRequests')).get_lang('RejectedCourseRequests').'</a>';
+echo ' <a href="course_request_accepted.php">'.Display::return_icon('course_request_accepted.gif', get_lang('AcceptedCourseRequests')).get_lang('AcceptedCourseRequests').'</a>';
+echo ' <a href="course_request_rejected.php">'.Display::return_icon('course_request_rejected.gif', get_lang('RejectedCourseRequests')).get_lang('RejectedCourseRequests').'</a>';
+echo '</div>';
+echo '<div class="actions">';
+$form->display();
 echo '</div>';
 
 // Create a sortable table with the course data.
 $offet = DELETE_ACTION_ENABLED ? 1 : 0;
-$table = new SortableTable('course_requests', 'get_number_of_requests', 'get_request_data', 1 + $offet);
+$table = new SortableTable('course_requests_review', 'get_number_of_requests', 'get_request_data', 4 + $offet, 20, 'DESC');
 $table->set_additional_parameters($parameters);
 if (DELETE_ACTION_ENABLED) {
     $table->set_header(0, '', false);

+ 8 - 4
main/create_course/add_course.php

@@ -85,6 +85,7 @@ $form->addElement('header', '', $tool_name);
 $form->addElement('text', 'title', get_lang('CourseName'), array('size' => '60', 'id' => 'title'));
 $form->applyFilter('title', 'html_filter');
 $form->addElement('static', null, null, get_lang('Ex'));
+$form->addRule('title', get_lang('ThisFieldIsRequired'), 'required');
 
 // Course category.
 $categories_select = $form->addElement('select', 'category_code', get_lang('Fac'), array());
@@ -96,6 +97,9 @@ $form->addElement('static', null, null, get_lang('TargetFac'));
 $form->add_textfield('wanted_code', get_lang('Code'), false, array('size' => '$maxlength', 'maxlength' => $maxlength));
 $form->applyFilter('wanted_code', 'html_filter');
 $form->addRule('wanted_code', get_lang('Max'), 'maxlength', $maxlength);
+if ($course_validation_feature) {
+    $form->addRule('wanted_code', get_lang('ThisFieldIsRequired'), 'required');
+}
 
 // The teacher.
 $titular = & $form->add_textfield('tutor_name', get_lang('Professor'), null, array('size' => '60', 'disabled' => 'disabled'));
@@ -106,15 +110,15 @@ if ($course_validation_feature) {
 
     // Description of the requested course.
     $form->addElement('textarea', 'description', get_lang('Description'), array('style' => 'border:#A5ACB2 solid 1px; font-family:arial,verdana,helvetica,sans-serif; font-size:12px', 'rows' => '3', 'cols' => '116'));
-    $form->addRule('description', get_lang('ThisFieldIsRequired'), 'required', '', '');
+    $form->addRule('description', get_lang('ThisFieldIsRequired'), 'required');
 
     // Objectives of the requested course.
     $form->addElement('textarea', 'objetives', get_lang('Objectives'), array('style' => 'border:#A5ACB2 solid 1px; font-family:arial,verdana,helvetica,sans-serif; font-size:12px', 'rows' => '3', 'cols' => '116'));
-    $form->addRule('objetives', get_lang('ThisFieldIsRequired'), 'required', '', '');
+    $form->addRule('objetives', get_lang('ThisFieldIsRequired'), 'required');
 
     // Target audience of the requested course.
     $form->addElement('textarea', 'target_audience', get_lang('TargetAudience'), array('style' => 'border:#A5ACB2 solid 1px; font-family:arial,verdana,helvetica,sans-serif; font-size:12px', 'rows' => '3', 'cols' => '116'));
-    $form->addRule('target_audience', get_lang('ThisFieldIsRequired'), 'required', '', '');
+    $form->addRule('target_audience', get_lang('ThisFieldIsRequired'), 'required');
 }
 
 // Course language.
@@ -136,7 +140,7 @@ if ($course_validation_feature) {
     if (!empty($terms_and_conditions_url)) {
         // Terms and conditions to be accepted before sending a course request.
         $form->addElement('checkbox', 'legal', get_lang('IAcceptTermsAndConditions'), '', 1);
-        $form->addRule('legal', get_lang('YouHaveToAcceptTermsAndConditions'), 'required', '', '');
+        $form->addRule('legal', get_lang('YouHaveToAcceptTermsAndConditions'), 'required');
         // Link to terms and conditions.
         $link_terms_and_conditions = '<script type="text/JavaScript">
         <!--

+ 11 - 3
main/inc/lib/course_request.lib.php

@@ -52,7 +52,7 @@ class CourseRequestManager {
      */
     public static function create_course_request($wanted_code, $title, $description, $category_code, $course_language, $objetives, $target_audience, $user_id) {
 
-        $wanted_code = Database::escape_string($wanted_code);
+        $wanted_code = trim(Database::escape_string($wanted_code));
         $title = Database::escape_string($title);
         $description = Database::escape_string($description);
         $category_code = Database::escape_string($category_code);
@@ -61,6 +61,10 @@ class CourseRequestManager {
         $target_audience = Database::escape_string($target_audience);
         $user_id = (int)$user_id;
 
+        if ($wanted_code == '') {
+            return false;
+        }
+
         if (self::course_code_exists($wanted_code)) {
             return false;
         }
@@ -182,7 +186,7 @@ class CourseRequestManager {
     public static function update_course_request($id, $wanted_code, $title, $description, $category_code, $course_language, $objetives, $target_audience, $user_id) {
 
         $id = (int)$id;
-        $wanted_code = Database::escape_string($wanted_code);
+        $wanted_code = trim(Database::escape_string($wanted_code));
         $title = Database::escape_string($title);
         $description = Database::escape_string($description);
         $category_code = Database::escape_string($category_code);
@@ -191,6 +195,10 @@ class CourseRequestManager {
         $target_audience = Database::escape_string($target_audience);
         $user_id = (int)$user_id;
 
+        if ($wanted_code == '') {
+            return false;
+        }
+
         if ($user_id <= 0) {
             return false;
         }
@@ -543,7 +551,7 @@ class CourseRequestManager {
      */
     public static function additional_info_asked($id) {
         $id = (int)$id;
-        $sql = "SELECT id FROM ".Database :: get_main_table(TABLE_MAIN_COURSE_REQUEST)." WHERE (id = ".$id." AND info = 1)";
+        $sql = "SELECT id FROM ".Database :: get_main_table(TABLE_MAIN_COURSE_REQUEST)." WHERE (id = ".$id." AND info > 0)";
         $result = Database::num_rows(Database::query($sql));
         return !empty($result);
     }