dokeos-forum
[ class tree: dokeos-forum ] [ index: dokeos-forum ] [ all elements ]

Source for file forumfunction.inc.php

Documentation is available at forumfunction.inc.php

  1. <?php
  2. /*
  3. ==============================================================================
  4.     Dokeos - elearning and course management software
  5.  
  6.     Copyright (c) 2006-2008 Dokeos SPRL
  7.     Copyright (c) 2006 Ghent University (UGent)
  8.  
  9.     For a full list of contributors, see "credits.txt".
  10.     The full license can be read in "license.txt".
  11.  
  12.     This program is free software; you can redistribute it and/or
  13.     modify it under the terms of the GNU General Public License
  14.     as published by the Free Software Foundation; either version 2
  15.     of the License, or (at your option) any later version.
  16.  
  17.     See the GNU General Public License for more details.
  18.  
  19.     Contact address: Dokeos, rue du Corbeau, 108, B-1030 Brussels, Belgium
  20.     Mail: info@dokeos.com
  21. ==============================================================================
  22. */
  23.  
  24. /**
  25. *    These files are a complete rework of the forum. The database structure is
  26. *    based on phpBB but all the code is rewritten. A lot of new functionalities
  27. *    are added:
  28. *     - forum categories and forums can be sorted up or down, locked or made invisible
  29. *    - consistent and integrated forum administration
  30. *     - forum options:     are students allowed to edit their post?
  31. *                         moderation of posts (approval)
  32. *                         reply only forums (students cannot create new threads)
  33. *                         multiple forums per group
  34. *    - sticky messages
  35. *     - new view option: nested view
  36. *     - quoting a message
  37. *
  38. *    @Author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  39. *    @Copyright Ghent University
  40. *    @Copyright Patrick Cool
  41. *
  42. *     @package dokeos.forum
  43. *
  44. @todo several functions have to be moved to the itemmanager library
  45. @todo displaying icons => display library
  46. @todo complete the missing phpdoc the correct order should be
  47. *
  48. *                  some explanation of the function
  49. *
  50. *                 @param 
  51. *                 @return 
  52. *
  53.                  @todo
  54. *
  55. *                 @author firstname lastname <email>, organisation
  56. *                 @version (day) month year
  57. *
  58. *                 @deprecated
  59. */
  60.  
  61. /**
  62.  *************************************************************************
  63.  *                        IMPORTANT NOTICE
  64.  * Please do not change anything is this code yet because there are still
  65.  * some significant code that need to happen and I do not have the time to
  66.  * merge files and test it all over again. So for the moment, please do not
  67.  * touch the code
  68.  *                             -- Patrick Cool <patrick.cool@UGent.be>
  69.  *************************************************************************
  70.  */
  71. require_once(api_get_path(INCLUDE_PATH).'/lib/mail.lib.inc.php');
  72. require_once(api_get_path(INCLUDE_PATH).'/conf/mail.conf.php');
  73. require_once(api_get_path(INCLUDE_PATH).'/lib/usermanager.lib.php');
  74. /**
  75. * This function handles all the forum and forumcategories actions. This is a wrapper for the
  76. * forum and forum categories. All this code code could go into the section where this function is
  77. * called but this make the code there cleaner.
  78. *
  79. @param 
  80. @return 
  81. *
  82. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  83. @version february 2006, dokeos 1.8
  84. */
  85. {
  86.     // Adding a forum category
  87.     if (($_GET['action']=='add' AND $_GET['content']=='forumcategory'OR $_POST['SubmitForumCategory')
  88.     {
  89.         show_add_forumcategory_form();
  90.     }
  91.     // Adding a forum
  92.     if ((($_GET['action']=='add' OR $_GET['action']=='edit'AND $_GET['content']=='forum'OR $_POST['SubmitForum')
  93.     {
  94.         if ($_GET['action']=='edit' and isset($_GET['id']OR $_POST['SubmitForum')
  95.         {
  96.             $inputvalues=get_forums(strval(intval($_GET['id'])))// note: this has to be cleaned first
  97.         }
  98.         show_add_forum_form($inputvalues);
  99.     }
  100.     // Edit a forum category
  101.     if (($_GET['action']=='edit' AND $_GET['content']=='forumcategory' AND isset($_GET['id'])) OR $_POST['SubmitEditForumCategory')
  102.     {
  103.         $forum_category=get_forum_categories(strval(intval($_GET['id'])))// note: this has to be cleaned first
  104.         show_edit_forumcategory_form($forum_category);
  105.     }
  106.     // Delete a forum category
  107.     if ($_GET['action']=='delete' AND isset($_GET['content']AND isset($_GET['id']))
  108.     {
  109.         $return_message=delete_forum_forumcategory_thread($_GET['content'],$_GET['id']);// note: this has to be cleaned first
  110.         Display :: display_confirmation_message($return_message,false);
  111.  
  112.     }
  113.     // Change visibility of a forum or a forum category
  114.     if (($_GET['action']=='invisible' OR $_GET['action']=='visible'AND isset($_GET['content']AND isset($_GET['id']))
  115.     {
  116.         $return_message=change_visibility($_GET['content']$_GET['id'],$_GET['action']);// note: this has to be cleaned first
  117.         Display :: display_confirmation_message($return_message,false);
  118.     }
  119.     // Change lock status of a forum or a forum category
  120.     if (($_GET['action']=='lock' OR $_GET['action']=='unlock'AND isset($_GET['content']AND isset($_GET['id']))
  121.     {
  122.         $return_message=change_lock_status($_GET['content']$_GET['id'],$_GET['action']);// note: this has to be cleaned first
  123.         Display :: display_confirmation_message($return_message,false);
  124.     }
  125.     // Move a forum or a forum category
  126.     if ($_GET['action']=='move' AND isset($_GET['content']AND isset($_GET['id']AND isset($_GET['direction']))
  127.     {
  128.         $return_message=move_up_down($_GET['content']$_GET['direction']$_GET['id']);// note: this has to be cleaned first
  129.         Display :: display_confirmation_message($return_message,false);
  130.     }
  131.  
  132. }
  133.  
  134. /**
  135. * This function displays the form that is used to add a forum category.
  136. *
  137. @param 
  138. @return 
  139. *
  140. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  141. @version february 2006, dokeos 1.8
  142. */
  143. function show_add_forumcategory_form($inputvalues=array())
  144. {
  145.     // initiate the object
  146.     $form new FormValidator('forumcategory');
  147.  
  148.     // settting the form elements
  149.     $form->addElement('header'''get_lang('AddForumCategory'));
  150.     $form->addElement('text''forum_category_title'get_lang('Title'),'class="input_titles"');
  151.     $form->addElement('html_editor''forum_category_comment'get_lang('Comment'));
  152.     $form->addElement('submit''SubmitForumCategory''OK');
  153.  
  154.     // setting the rules
  155.     $form->addRule('forum_category_title''<div class="required">'.get_lang('ThisFieldIsRequired')'required');
  156.  
  157.     // The validation or display
  158.     if$form->validate() )
  159.     {
  160.        $values $form->exportValues();
  161.        store_forumcategory($values);
  162.     }
  163.     else
  164.     {
  165.         $form->display();
  166.     }
  167. }
  168.  
  169.  
  170. /**
  171. * This function displays the form that is used to add a forum category.
  172. *
  173. @param 
  174. @return 
  175. *
  176. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  177. @version february 2006, dokeos 1.8
  178. */
  179. function show_add_forum_form($inputvalues=array())
  180. {
  181.     global $_course;
  182.  
  183.     // initiate the object
  184.     $form new FormValidator('forumcategory''post''index.php');
  185.  
  186.     // the header for the form
  187.     $session_header = isset($_SESSION['session_name']' ('.$_SESSION['session_name'].') ' '';
  188.     $form->addElement('header'''get_lang('AddForum').$session_header);
  189.  
  190.     // we have a hidden field if we are editing
  191.     if (is_array($inputvalues))
  192.     {
  193.         $form->addElement('hidden''forum_id'$inputvalues['forum_id']);
  194.     }
  195.  
  196.     // The title of the forum
  197.     $form->addElement('text''forum_title'get_lang('Title'),'class="input_titles"');
  198.  
  199.     // The comment of the forum
  200.     $form->addElement('html_editor''forum_comment'get_lang('Comment'));
  201.  
  202.     // dropdown list: Forum Categories
  203.     $forum_categories=get_forum_categories();
  204.     foreach ($forum_categories as $key=>$value)
  205.     {
  206.         $forum_categories_titles[$value['cat_id']]=$value['cat_title'];
  207.     }
  208.     $form->addElement('select''forum_category'get_lang('InForumCategory')$forum_categories_titles);
  209.  
  210.     if ($_course['visibility']==COURSE_VISIBILITY_OPEN_WORLD)
  211.     {
  212.         // This is for vertical
  213.         //$form->addElement('radio', 'allow_anonymous', get_lang('AllowAnonymousPosts'), get_lang('Yes'), 1);
  214.         //$form->addElement('radio', 'allow_anonymous', '', get_lang('No'), 0);
  215.         // This is for horizontal
  216.         $group='';
  217.         $group[=HTML_QuickForm::createElement('radio''allow_anonymous',null,get_lang('Yes'),1);
  218.         $group[=HTML_QuickForm::createElement('radio''allow_anonymous',null,get_lang('No'),0);
  219.         $form->addGroup($group'allow_anonymous_group'get_lang('AllowAnonymousPosts')'&nbsp;');
  220.     }
  221.  
  222.     // This is for vertical
  223.     //$form->addElement('radio', 'students_can_edit', get_lang('StudentsCanEdit'), get_lang('Yes'), 1);
  224.     //$form->addElement('radio', 'students_can_edit', '', get_lang('No'), 0);
  225.     // This is for horizontal
  226.     $group='';
  227.     $group[=HTML_QuickForm::createElement('radio''students_can_edit',null,get_lang('Yes'),1);
  228.     $group[=HTML_QuickForm::createElement('radio''students_can_edit',null,get_lang('No'),0);
  229.     $form->addGroup($group'students_can_edit_group'get_lang('StudentsCanEdit')'&nbsp;');
  230.  
  231.     // This is for vertical
  232.     //$form->addElement('radio', 'approval_direct', get_lang('ApprovalDirect'), get_lang('Approval'), 1);
  233.     //$form->addElement('radio', 'approval_direct', '', get_lang('Direct'), 0);
  234.     // This is for horizontal
  235.     $group='';
  236.     $group[=HTML_QuickForm::createElement('radio''approval_direct',null,get_lang('Approval'),1);
  237.     $group[=HTML_QuickForm::createElement('radio''approval_direct',null,get_lang('Direct'),0);
  238.     //$form->addGroup($group, 'approval_direct_group', get_lang('ApprovalDirect'), '&nbsp;');
  239.  
  240.  
  241.     // This is for vertical
  242.     //$form->addElement('radio', 'allow_attachments', get_lang('AllowAttachments'), get_lang('Yes'), 1);
  243.     //$form->addElement('radio', 'allow_attachments', '', get_lang('No'), 0);
  244.     // This is for horizontal
  245.     $group='';
  246.     $group[=HTML_QuickForm::createElement('radio''allow_attachments',null,get_lang('Yes'),1);
  247.     $group[=HTML_QuickForm::createElement('radio''allow_attachments',null,get_lang('No'),0);
  248.     //$form->addGroup($group, 'allow_attachments_group', get_lang('AllowAttachments'), '&nbsp;');
  249.  
  250.     // This is for vertical
  251.     //$form->addElement('radio', 'allow_new_threads', get_lang('AllowNewThreads'), 1, get_lang('Yes'));
  252.     //$form->addElement('radio', 'allow_new_threads', '', 0, get_lang('No'));
  253.     // This is for horizontal
  254.     $group='';
  255.     $group[=HTML_QuickForm::createElement('radio''allow_new_threads',nullget_lang('Yes'),1);
  256.     $group[=HTML_QuickForm::createElement('radio''allow_new_threads',nullget_lang('No'),0);
  257.     $form->addGroup($group'allow_new_threads_group'get_lang('AllowNewThreads')'&nbsp;');
  258.  
  259.     $group='';
  260.     $group[=HTML_QuickForm::createElement('radio''default_view_type'nullget_lang('Flat')'flat');
  261.     $group[=HTML_QuickForm::createElement('radio''default_view_type'nullget_lang('Threaded')'threaded');
  262.     $group[=HTML_QuickForm::createElement('radio''default_view_type'nullget_lang('Nested')'nested');
  263.     $form->addGroup($group'default_view_type_group'get_lang('DefaultViewType')'&nbsp;');
  264.  
  265.  
  266.     $form->addElement('static','Group''<br /><strong>'.get_lang('GroupSettings').'</strong>');
  267.  
  268.     // dropdown list: Groups
  269.     $groups=GroupManager::get_group_list();
  270.     $groups_titles[0]=get_lang('NotAGroupForum');
  271.     foreach ($groups as $key=>$value)
  272.     {
  273.         $groups_titles[$value['id']]=$value['name'];
  274.     }
  275.     $form->addElement('select''group_forum'get_lang('ForGroup')$groups_titles);
  276.  
  277.     // Public or private group forum
  278.     $group='';
  279.     $group[=HTML_QuickForm::createElement('radio''public_private_group_forum'nullget_lang('Public')'public');
  280.     $group[=HTML_QuickForm::createElement('radio''public_private_group_forum'nullget_lang('Private')'private');
  281.     $form->addGroup($group'public_private_group_forum_group'get_lang('PublicPrivateGroupForum')'&nbsp;');
  282.  
  283.  
  284.     // The OK button
  285.     $form->addElement('submit''SubmitForum''OK');
  286.  
  287.     // setting the rules
  288.     $form->addRule('forum_title'get_lang('ThisFieldIsRequired')'required');
  289.     $form->addRule('forum_category'get_lang('ThisFieldIsRequired')'required');
  290.  
  291.     global $charset;
  292.     
  293.     // settings the defaults
  294.     if (!is_array($inputvalues))
  295.     {
  296.         $defaults['allow_anonymous_group']['allow_anonymous']=0;
  297.         $defaults['students_can_edit_group']['students_can_edit']=0;
  298.         $defaults['approval_direct_group']['approval_direct']=0;
  299.         $defaults['allow_attachments_group']['allow_attachments']=1;
  300.         $defaults['allow_new_threads_group']['allow_new_threads']=1;
  301.         $defaults['default_view_type_group']['default_view_type']=api_get_setting('default_forum_view');
  302.         $defaults['public_private_group_forum_group']['public_private_group_forum']='public';
  303.         if (isset($_GET['forumcategory']))
  304.         {
  305.             $defaults['forum_category']=$_GET['forumcategory'];
  306.         }
  307.     }
  308.     else  // the default values when editing = the data in the table
  309.     {
  310.         $defaults['forum_id']=$inputvalues['forum_id'];
  311.         $defaults['forum_title']=prepare4display(html_entity_decode($inputvalues['forum_title'],ENT_QUOTES,$charset));
  312.         $defaults['forum_comment']=prepare4display($inputvalues['forum_comment']);
  313.         $defaults['forum_category']=$inputvalues['forum_category'];
  314.         $defaults['allow_anonymous_group']['allow_anonymous']=$inputvalues['allow_anonymous'];
  315.         $defaults['students_can_edit_group']['students_can_edit']=$inputvalues['allow_edit'];
  316.         $defaults['approval_direct_group']['approval_direct']=$inputvalues['approval_direct_post'];
  317.         $defaults['allow_attachments_group']['allow_attachments']=$inputvalues['allow_attachments'];
  318.         $defaults['allow_new_threads_group']['allow_new_threads']=$inputvalues['allow_new_threads'];
  319.         $defaults['default_view_type_group']['default_view_type']=$inputvalues['default_view'];
  320.         $defaults['public_private_group_forum_group']['public_private_group_forum']=$inputvalues['forum_group_public_private'];
  321.         $defaults['group_forum']=$inputvalues['forum_of_group'];
  322.     }
  323.     $form->setDefaults($defaults);
  324.  
  325.  
  326.     // The validation or display
  327.     if$form->validate() )
  328.     {
  329.        $values $form->exportValues();
  330.        store_forum($values);
  331.     }
  332.     else
  333.     {
  334.         $form->display();
  335.     }
  336. }
  337.  
  338.  
  339.  
  340. /**
  341. * This function displays the form that is used to edit a forum category.
  342. * This is more or less a copy from the show_add_forumcategory_form function with the only difference that is uses
  343. * some default values. I tried to have both in one function but this gave problems with the handle_forum_and_forumcategories function
  344. * (storing was done twice)
  345. *
  346. @param 
  347. @return 
  348. *
  349. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  350. @version february 2006, dokeos 1.8
  351. */
  352. function show_edit_forumcategory_form($inputvalues=array())
  353. {
  354.     // initiate the object
  355.     $form new FormValidator('forumcategory');
  356.  
  357.     // settting the form elements
  358.     $form->addElement('header'''get_lang('EditForumCategory'));
  359.     $form->addElement('hidden''forum_category_id');
  360.     $form->addElement('text''forum_category_title'get_lang('Title'),'class="input_titles"');
  361.     $form->addElement('html_editor''forum_category_comment'get_lang('Comment'));
  362.     $form->addElement('submit''SubmitEditForumCategory''OK');
  363.     global $charset;
  364.     // setting the default values
  365.     $defaultvalues['forum_category_id']=$inputvalues['cat_id'];
  366.  
  367.     $defaultvalues['forum_category_title']=prepare4display(html_entity_decode($inputvalues['cat_title'],ENT_QUOTES,$charset));
  368.     $defaultvalues['forum_category_comment']=prepare4display($inputvalues['cat_comment']);
  369.     $form->setDefaults($defaultvalues);
  370.  
  371.     // setting the rules
  372.     $form->addRule('forum_category_title'get_lang('ThisFieldIsRequired')'required');
  373.  
  374.     // The validation or display
  375.     if$form->validate() )
  376.     {
  377.        $values $form->exportValues();
  378.        store_forumcategory($values);
  379.     }
  380.     else
  381.     {
  382.         $form->display();
  383.     }
  384. }
  385.  
  386.  
  387.  
  388. /**
  389. * This function stores the forum category in the database. The new category is added to the end.
  390. *
  391. @param 
  392. @return 
  393. *
  394. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  395. @version february 2006, dokeos 1.8
  396. */
  397. function store_forumcategory($values)
  398. {
  399.     global $table_categories;
  400.     global $_course;
  401.     global $_user;
  402.  
  403.     // find the max cat_order. The new forum category is added at the end => max cat_order + &
  404.     $sql="SELECT MAX(cat_order) as sort_max FROM ".Database::escape_string($table_categories);
  405.     $result=api_sql_query($sql,__FILE__,__LINE__);
  406.     $row=Database::fetch_array($result);
  407.     $new_max=$row['sort_max']+1;
  408.     
  409.     $clean_cat_title=Security::remove_XSS(Database::escape_string($values['forum_category_title']));
  410.  
  411.     if (isset($values['forum_category_id']))
  412.     // storing an edit
  413.         $sql="UPDATE ".$table_categories." SET cat_title='".$clean_cat_title."', cat_comment='".Database::escape_string($values['forum_category_comment'])."' WHERE cat_id='".Database::escape_string($values['forum_category_id'])."'";
  414.         api_sql_query($sql,__FILE__,__LINE__);
  415.         $last_id=Database::get_last_insert_id();
  416.         api_item_property_update($_courseTOOL_FORUM_CATEGORY$values['forum_category_id'],"ForumCategoryAdded"api_get_user_id());
  417.         $return_message=get_lang('ForumCategoryEdited');
  418.     }
  419.     else
  420.     {
  421.         $sql="INSERT INTO ".$table_categories." (cat_title, cat_comment, cat_order) VALUES ('".$clean_cat_title."','".Database::escape_string($values['forum_category_comment'])."','".Database::escape_string($new_max)."')";
  422.         api_sql_query($sql,__FILE__,__LINE__);
  423.         $last_id=Database::get_last_insert_id();
  424.         api_item_property_update($_courseTOOL_FORUM_CATEGORY$last_id,"ForumCategoryAdded"api_get_user_id());
  425.         $return_message=get_lang('ForumCategoryAdded');
  426.     }
  427.  
  428.     Display :: display_confirmation_message($return_message);
  429. }
  430.  
  431. /**
  432. * This function stores the forum in the database. The new forum is added to the end.
  433. *
  434. @param 
  435. @return 
  436. *
  437. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  438. @version february 2006, dokeos 1.8
  439. */
  440. function store_forum($values)
  441. {
  442.     global $_course;
  443.     global $_user;
  444.     
  445.     $table_forums Database::get_course_table(TABLE_FORUM);
  446.  
  447.     // find the max forum_order for the given category. The new forum is added at the end => max cat_order + &
  448.     $sql="SELECT MAX(forum_order) as sort_max FROM ".$table_forums." WHERE forum_category=".Database::escape_string($values['forum_category']);
  449.     $result=api_sql_query($sql,__FILE__,__LINE__);
  450.     $row=Database::fetch_array($result);
  451.     $new_max=$row['sort_max']+1;
  452.     $session_id = isset($_SESSION['id_session']$_SESSION['id_session'0;
  453.     
  454.     $clean_title=Security::remove_XSS(Database::escape_string(htmlspecialchars($values['forum_title'])));
  455.     
  456.     if (isset($values['forum_id']))
  457.     {
  458.     
  459.     // storing an edit
  460.         $sql="UPDATE ".$table_forums." SET
  461.                     forum_title='".$clean_title."',
  462.                     forum_comment='".Database::escape_string($values['forum_comment'])."',
  463.                     forum_category='".Database::escape_string($values['forum_category'])."',
  464.                     allow_anonymous='".Database::escape_string($values['allow_anonymous_group']['allow_anonymous'])."',
  465.                     allow_edit='".Database::escape_string($values['students_can_edit_group']['students_can_edit'])."',
  466.                     approval_direct_post='".Database::escape_string($values['approval_direct_group']['approval_direct'])."',
  467.                     allow_attachments='".Database::escape_string($values['allow_attachments_group']['allow_attachments'])."',
  468.                     allow_new_threads='".Database::escape_string($values['allow_new_threads_group']['allow_new_threads'])."',
  469.                     forum_group_public_private='".Database::escape_string($values['public_private_group_forum_group']['public_private_group_forum'])."',
  470.                     default_view='".Database::escape_string($values['default_view_type_group']['default_view_type'])."',
  471.                     forum_of_group='".Database::escape_string($values['group_forum'])."'
  472.                 WHERE forum_id='".Database::escape_string($values['forum_id'])."'";
  473.         api_sql_query($sql,__FILE__,__LINE__);
  474.         $return_message=get_lang('ForumEdited');
  475.     }
  476.     else
  477.     {
  478.         $sql="INSERT INTO ".$table_forums."
  479.                     (forum_title, forum_comment, forum_category, allow_anonymous, allow_edit, approval_direct_post, allow_attachments, allow_new_threads, default_view, forum_of_group, forum_group_public_private, forum_order, session_id)
  480.                     VALUES ('".$clean_title."',
  481.                         '".Database::escape_string($values['forum_comment'])."',
  482.                         '".Database::escape_string($values['forum_category'])."',
  483.                         '".Database::escape_string($values['allow_anonymous_group']['allow_anonymous'])."',
  484.                         '".Database::escape_string($values['students_can_edit_group']['students_can_edit'])."',
  485.                         '".Database::escape_string($values['approval_direct_group']['approval_direct'])."',
  486.                         '".Database::escape_string($values['allow_attachments_group']['allow_attachments'])."',
  487.                         '".Database::escape_string($values['allow_new_threads_group']['allow_new_threads'])."',
  488.                         '".Database::escape_string($values['default_view_type_group']['default_view_type'])."',
  489.                         '".Database::escape_string($values['group_forum'])."',
  490.                         '".Database::escape_string($values['public_private_group_forum_group']['public_private_group_forum'])."',
  491.                         '".Database::escape_string($new_max)."',
  492.                         ".intval($session_id).")";
  493.         api_sql_query($sql__LINE__,__FILE__);
  494.         $last_id=Database::get_last_insert_id();
  495.         api_item_property_update($_courseTOOL_FORUM$last_id,"ForumCategoryAdded"api_get_user_id());
  496.         $return_message=get_lang('ForumAdded');
  497.     }
  498.     return $return_message;
  499. }
  500.  
  501. /**
  502. * This function deletes a forum or a forum category
  503. * This function currently does not delete the forums inside the category, nor the threads and replies inside these forums.
  504. * For the moment this is the easiest method and it has the advantage that it allows to recover fora that were acidently deleted
  505. * when the forum category got deleted.
  506. *
  507. @param $content = what we are deleting (a forum or a forum category)
  508. @param $id The id of the forum category that has to be deleted.
  509. *
  510. @todo write the code for the cascading deletion of the forums inside a forum category and also the threads and replies inside these forums
  511. @todo config setting for recovery or not (see also the documents tool: real delete or not).
  512. *
  513. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  514. @version february 2006, dokeos 1.8
  515. */
  516. function delete_forum_forumcategory_thread($content$id)
  517. {
  518.     global $_course;
  519.  
  520.     if ($content=='forumcategory')
  521.     {
  522.         $tool_constant=TOOL_FORUM_CATEGORY;
  523.         $return_message=get_lang('ForumCategoryDeleted');
  524.     }
  525.     if ($content=='forum')
  526.     {
  527.         $tool_constant=TOOL_FORUM;
  528.         $return_message=get_lang('ForumDeleted');
  529.     }
  530.     if ($content=='thread')
  531.     {
  532.         $tool_constant=TOOL_FORUM_THREAD;
  533.         $return_message=get_lang('ThreadDeleted');
  534.     }
  535.     api_item_property_update($_course,$tool_constant,$id,'delete',api_get_user_id())// note: check if this returns a true and if so => return $return_message, if not => return false;
  536.     //delete_attachment($post_id);
  537.     return $return_message;
  538. }
  539.  
  540. /**
  541. * This function deletes a forum post. This separate function is needed because forum posts do not appear in the item_property table (yet)
  542. * and because deleting a post also has consequence on the posts that have this post as parent_id (they are also deleted).
  543. * an alternative would be to store the posts also in item_property and mark this post as deleted (visibility = 2).
  544. * We also have to decrease the number of replies in the thread table
  545. *
  546. @param $post_id the id of the post that will be deleted
  547. *
  548. @todo write recursive function that deletes all the posts that have this message as parent
  549. *
  550. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  551. @version february 2006, dokeos 1.8
  552. */
  553. function delete_post($post_id)
  554. {
  555.     global $table_posts;
  556.     global $table_threads;
  557.  
  558.     $sql="DELETE FROM $table_posts WHERE post_id='".Database::escape_string($post_id)."'"// note: this has to be a recursive function that deletes all of the posts in this block.
  559.     api_sql_query($sql,__FILE__,__LINE__);
  560.     
  561.     delete_attachment($post_id);
  562.     
  563.     $last_post_of_thread=check_if_last_post_of_thread(strval(intval($_GET['thread'])));
  564.     
  565.     if (is_array($last_post_of_thread))
  566.     {
  567.         // Decreasing the number of replies for this thread and also changing the last post information
  568.         $sql="UPDATE $table_threads SET thread_replies=thread_replies-1,
  569.                     thread_last_post='".Database::escape_string($last_post_of_thread['post_id'])."',
  570.                     thread_date='".Database::escape_string($last_post_of_thread['post_date'])."'
  571.             WHERE thread_id='".Database::escape_string($_GET['thread'])."'";
  572.         api_sql_query($sql,__FILE__,__LINE__);
  573.         return 'PostDeleted';
  574.     }
  575.     if ($last_post_of_thread==false)
  576.     {
  577.         // we deleted the very single post of the thread so we need to delete the entry in the thread table also.
  578.         $sql="DELETE FROM $table_threads WHERE thread_id='".Database::escape_string($_GET['thread'])."'";
  579.         api_sql_query($sql,__FILE__,__LINE__);
  580.         return 'PostDeletedSpecial';
  581.     }
  582. }
  583.  
  584.  
  585. /**
  586. * This function gets the all information of the last (=most recent) post of the thread
  587. * This can be done by sorting the posts that have the field thread_id=$thread_id and sort them by post_date
  588. *
  589. @param $thread_id the id of the thread we want to know the last post of.
  590. @return an array if there is a last post found, false if there is no post entry linked to that thread => thread will be deleted
  591. *
  592. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  593. @version february 2006, dokeos 1.8
  594. */
  595. function check_if_last_post_of_thread($thread_id)
  596. {
  597.     global $table_posts;
  598.  
  599.     $sql="SELECT * FROM $table_posts WHERE thread_id='".Database::escape_string($thread_id)."' ORDER BY post_date DESC";
  600.     $result=api_sql_query($sql,__FILE__,__LINE__);
  601.     if (Database::num_rows($result)>0)
  602.     {
  603.         $row=Database::fetch_array($result);
  604.         return $row;
  605.     }
  606.     else
  607.     {
  608.         return false;
  609.     }
  610. }
  611.  
  612.  
  613. /**
  614. * This function takes care of the display of the visibility icon
  615. *
  616. @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  617. @param $id the id of the content we want to make invisible
  618. @param $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
  619. @return 
  620. *
  621. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  622. @version february 2006, dokeos 1.8
  623. */
  624. function display_visible_invisible_icon($content$id$current_visibility_status$additional_url_parameters='')
  625. {
  626.     $id Security::remove_XSS($id);
  627.     if ($current_visibility_status=='1')
  628.     {
  629.         echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
  630.         if (is_array($additional_url_parameters))
  631.         {
  632.             foreach ($additional_url_parameters as $key=>$value)
  633.             {
  634.                 echo $key.'='.$value.'&amp;';
  635.             }
  636.         }
  637.         echo 'action=invisible&amp;content='.$content.'&amp;id='.$id.'">'.icon('../img/visible.gif',get_lang('MakeInvisible')).'</a>';
  638.     }
  639.     if ($current_visibility_status=='0')
  640.     {
  641.         echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
  642.         if (is_array($additional_url_parameters))
  643.         {
  644.             foreach ($additional_url_parameters as $key=>$value)
  645.             {
  646.                 echo $key.'='.$value.'&amp;';
  647.             }
  648.         }
  649.         echo 'action=visible&amp;content='.$content.'&amp;id='.$id.'">'.icon('../img/invisible.gif',get_lang('MakeVisible')).'</a>';
  650.     }
  651. }
  652.  
  653. /**
  654. * This function takes care of the display of the lock icon
  655. *
  656. @param $content what is it that we want to (un)lock: forum category, forum, thread, post
  657. @param $id the id of the content we want to (un)lock
  658. @param $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
  659. @return 
  660. *
  661. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  662. @version february 2006, dokeos 1.8
  663. */
  664. function display_lock_unlock_icon($content$id$current_lock_status$additional_url_parameters='')
  665. {
  666.     $id Security::remove_XSS($id);
  667.     if ($current_lock_status=='1')
  668.     {
  669.         echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
  670.         if (is_array($additional_url_parameters))
  671.         {
  672.             foreach ($additional_url_parameters as $key=>$value)
  673.             {
  674.                 echo $key.'='.$value.'&amp;';
  675.             }
  676.         }
  677.         echo 'action=unlock&amp;content='.$content.'&amp;id='.$id.'">'.icon('../img/lock.gif',get_lang('Unlock')).'</a>';
  678.     }
  679.     if ($current_lock_status=='0')
  680.     {
  681.         echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
  682.         if (is_array($additional_url_parameters))
  683.         {
  684.             foreach ($additional_url_parameters as $key=>$value)
  685.             {
  686.                 echo $key.'='.$value.'&amp;';
  687.             }
  688.         }
  689.         echo 'action=lock&amp;content='.$content.'&amp;id='.$id.'">'.icon('../img/unlock.gif',get_lang('Lock')).'</a>';
  690.     }
  691. }
  692.  
  693. /**
  694. * This function takes care of the display of the up and down icon
  695. *
  696. @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  697. @param $id is the id of the item we want to display the icons for
  698. @param $list is an array of all the items. All items in this list should have an up and down icon except for the first (no up icon) and the last (no down icon)
  699. *           The key of this $list array is the id of the item.
  700. *
  701. @return 
  702. *
  703. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  704. @version february 2006, dokeos 1.8
  705. */
  706. function display_up_down_icon($content$id$list)
  707. {
  708.     $id strval(intval($id));
  709.     $total_items=count($list);
  710.     $position 0;
  711.     $internal_counter=0;
  712.  
  713.     if(is_array($list))
  714.     {
  715.         foreach ($list as $key=>$listitem)
  716.         {
  717.             $internal_counter++;
  718.             if ($id==$key)
  719.             {
  720.                 $position=$internal_counter;
  721.             }
  722.         }
  723.     }
  724.     if ($position>1)
  725.     {
  726.         $return_value='<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&amp;direction=up&amp;content='.$content.'&amp;id='.$id.'" title="'.get_lang('MoveUp').'"><img src="../img/up.gif" /></a>';
  727.     }
  728.     else
  729.     {
  730.         $return_value='<img src="../img/up_na.gif" />';
  731.     }
  732.     
  733.     if ($position<$total_items)
  734.     {
  735.         $return_value.='<a href="'.api_get_self().'?'.api_get_cidreq().'&action=move&amp;direction=down&amp;content='.$content.'&amp;id='.$id.'" title="'.get_lang('MoveDown').'" ><img src="../img/down.gif" /></a>';
  736.     }    
  737.     else
  738.     {
  739.         
  740.        $return_value.='<img src="../img/down_na.gif" />';
  741.     }
  742.  
  743.     echo $return_value;
  744. }
  745.  
  746.  
  747.  
  748.  
  749. /**
  750. * This function changes the visibility in the database (item_property)
  751. *
  752. @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  753. @param $id the id of the content we want to make invisible
  754. @param $target_visibility what is the current status of the visibility (0 = invisible, 1 = visible)
  755. *
  756. @todo change the get parameter so that it matches the tool constants.
  757. @todo check if api_item_property_update returns true or false => returnmessage depends on it.
  758. @todo move to itemmanager
  759. *
  760. @return 
  761. *
  762. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  763. @version february 2006, dokeos 1.8
  764. */
  765. function change_visibility($content$id$target_visibility)
  766. {
  767.     global $_course;
  768.     $constants=array('forumcategory'=>TOOL_FORUM_CATEGORY'forum'=>TOOL_FORUM'thread'=>TOOL_FORUM_THREAD);
  769.     api_item_property_update($_course,$constants[$content],$id,$target_visibility,api_get_user_id())// note: check if this returns true or false => returnmessage depends on it.
  770.     if ($target_visibility=='visible')
  771.     {
  772.         handle_mail_cue($content$id);
  773.     }
  774.  
  775.     return get_lang('VisibilityChanged');
  776. }
  777.  
  778.  
  779. /**
  780. * This function changes the lock status in the database
  781. *
  782. @param $content what is it that we want to (un)lock: forum category, forum, thread, post
  783. @param $id the id of the content we want to (un)lock
  784. @param $action do we lock (=>locked value in db = 1) or unlock (=> locked value in db = 0)
  785. @return string, language variable
  786. *
  787. @todo move to itemmanager
  788. *
  789. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  790. @version february 2006, dokeos 1.8
  791. */
  792. function change_lock_status($content$id$action)
  793. {
  794.     global $table_categories;
  795.     global $table_forums;
  796.     global $table_threads;
  797.     global $table_posts;
  798.  
  799.     // Determine the relevant table
  800.     if ($content=='forumcategory')
  801.     {
  802.         $table=$table_categories;
  803.         $id_field='cat_id';
  804.     }
  805.     elseif ($content=='forum')
  806.     {
  807.         $table=$table_forums;
  808.         $id_field='forum_id';
  809.     }
  810.     elseif ($content=='thread')
  811.     {
  812.         $table=$table_threads;
  813.         $id_field='thread_id';
  814.     }
  815.     else
  816.     {
  817.         return get_lang('Error');
  818.     }
  819.  
  820.     // Determine what we are doing => defines the value for the database and the return message
  821.     if ($action=='lock')
  822.     {
  823.         $db_locked=1;
  824.         $return_message=get_lang('Locked');
  825.     }
  826.     elseif ($action=='unlock')
  827.     {
  828.         $db_locked=0;
  829.         $return_message=get_lang('Unlocked');
  830.     }
  831.     else
  832.     {
  833.         return get_lang('Error');
  834.     }
  835.  
  836.     // Doing the change in the database
  837.     $sql="UPDATE $table SET locked='".Database::escape_string($db_locked)."' WHERE $id_field='".Database::escape_string($id)."'";
  838.     if (api_sql_query($sql,__FILE__,__LINE__))
  839.     {
  840.         return $return_message;
  841.     }
  842.     else
  843.     {
  844.         return get_lang('Error');
  845.     }
  846. }
  847.  
  848.  
  849. /**
  850. * This function moves a forum or a forum category up or down
  851. *
  852. @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  853. @param $direction do we want to move it up or down.
  854. @param $id the id of the content we want to make invisible
  855. @todo consider removing the table_item_property calls here but this can prevent unwanted side effects when a forum does not have an entry in
  856. *          the item_property table but does have one in the forum table.
  857. @return 
  858. *
  859. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  860. @version february 2006, dokeos 1.8
  861. */
  862. function move_up_down($content$direction$id)
  863. {
  864.     global $table_categories;
  865.     global $table_forums;
  866.     global $table_item_property;
  867.  
  868.  
  869.     // Determine which field holds the sort order
  870.     if ($content=='forumcategory')
  871.     {
  872.         $table=$table_categories;
  873.         $sort_column='cat_order';
  874.         $id_column='cat_id';
  875.         $sort_column='cat_order';
  876.     }
  877.     elseif ($content=='forum')
  878.     {
  879.         $table=$table_forums;
  880.         $sort_column='forum_order';
  881.         $id_column='forum_id';
  882.         $sort_column='forum_order';
  883.         // we also need the forum_category of this forum
  884.         $sql="SELECT forum_category FROM $table_forums WHERE forum_id=".Database::escape_string($id);
  885.         $result=api_sql_query($sql,__FILE__,__LINE__);
  886.         $row=Database::fetch_array($result);
  887.         $forum_category=$row['forum_category'];
  888.     }
  889.     else
  890.     {
  891.         return get_lang('Error');
  892.     }
  893.  
  894.     // determine if need to sort ascending or descending
  895.     if ($direction=='down')
  896.     {
  897.         $sort_direction='ASC';
  898.     }
  899.     elseif ($direction=='up')
  900.     {
  901.         $sort_direction='DESC';
  902.     }
  903.     else
  904.     {
  905.         return get_lang('Error');
  906.     }
  907.  
  908.     // The SQL statement
  909.     if ($content=='forumcategory')
  910.     {
  911.         $sql="SELECT * FROM".$table_categories." forum_categories, ".$table_item_property." item_properties
  912.                     WHERE forum_categories.cat_id=item_properties.ref
  913.                     AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  914.                     ORDER BY forum_categories.cat_order $sort_direction";
  915.     }
  916.     if ($content=='forum')
  917.     {
  918.         $sql="SELECT * FROM".$table." WHERE forum_category='".Database::escape_string($forum_category)."' ORDER BY forum_order $sort_direction";
  919.     }
  920.  
  921.  
  922.     // echo $sql.'<br />';
  923.  
  924.  
  925.     // finding the items that need to be switched
  926.     $result=api_sql_query($sql,__FILE__,__LINE__);
  927.     $found=false;
  928.     while ($row=Database::fetch_array($result))
  929.     {
  930.         //echo $row[$id_column].'-';
  931.         if ($found==true)
  932.         {
  933.             $next_id=$row[$id_column];
  934.             $next_sort=$row[$sort_column];
  935.             $found=false;
  936.         }
  937.         if($id==$row[$id_column])
  938.         {
  939.             $this_id=$id;
  940.             $this_sort=$row[$sort_column];
  941.             $found=true;
  942.         }
  943.     }
  944.  
  945.     // Committing the switch
  946.     // we do an extra check if we do not have illegal values. If your remove this if statment you will
  947.     // be able to mess with the sorting by refreshing the page over and over again.
  948.     if ($this_sort<>'' AND $next_sort<>'' AND $next_id<>'' AND $this_id<>'')
  949.     {
  950.         $sql_update1="UPDATE $table SET $sort_column='".Database::escape_string($this_sort)."' WHERE $id_column='".Database::escape_string($next_id)."'";
  951.         $sql_update2="UPDATE $table SET $sort_column='".Database::escape_string($next_sort)."' WHERE $id_column='".Database::escape_string($this_id)."'";
  952.         api_sql_query($sql_update1,__FILE__,__LINE__);
  953.         api_sql_query($sql_update2,__FILE__,__LINE__);
  954.     }
  955.  
  956.     return get_lang(ucfirst($content).'Moved');
  957. }
  958.  
  959.  
  960. /**
  961. * This function returns a piece of html code that make the links grey (=invisible for the student)
  962. *
  963. @param boolean 0/1: 0 = invisible, 1 = visible
  964. @return string 
  965. *
  966. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  967. @version february 2006, dokeos 1.8
  968. */
  969. function class_visible_invisible($current_visibility_status)
  970. {
  971.     if ($current_visibility_status=='0')
  972.     {
  973.         return "class='invisible'";
  974.     }
  975. }
  976.  
  977. /**
  978. * Retrieve all the information off the forum categories (or one specific) for the current course.
  979. * The categories are sorted according to their sorting order (cat_order
  980. *
  981. @param $id default ''. When an id is passed we only find the information about that specific forum category. If no id is passed we get all the forum categories.
  982. @return an array containing all the information about all the forum categories
  983. *
  984. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  985. @version february 2006, dokeos 1.8
  986. */
  987. function get_forum_categories($id='')
  988. {
  989.     $table_categories        Database :: get_course_table(TABLE_FORUM_CATEGORY);
  990.     $table_item_property    Database :: get_course_table(TABLE_ITEM_PROPERTY);
  991.  
  992.     if ($id=='')
  993.     {
  994.         $sql="SELECT * FROM".$table_categories." forum_categories, ".$table_item_property." item_properties
  995.                     WHERE forum_categories.cat_id=item_properties.ref
  996.                     AND item_properties.visibility=1
  997.                     AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  998.                     ORDER BY forum_categories.cat_order ASC";
  999.         if (is_allowed_to_edit())
  1000.         {
  1001.             $sql="SELECT * FROM".$table_categories." forum_categories, ".$table_item_property." item_properties
  1002.                     WHERE forum_categories.cat_id=item_properties.ref
  1003.                     AND item_properties.visibility<>2
  1004.                     AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  1005.                     ORDER BY forum_categories.cat_order ASC";
  1006.         }
  1007.     }
  1008.     else
  1009.     {
  1010.         $sql="SELECT * FROM".$table_categories." forum_categories, ".$table_item_property." item_properties
  1011.                 WHERE forum_categories.cat_id=item_properties.ref
  1012.                 AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  1013.                 AND forum_categories.cat_id='".Database::escape_string($id)."'
  1014.                 ORDER BY forum_categories.cat_order ASC";
  1015.     }
  1016.     $result=api_sql_query($sql,__FILE__,__LINE__);
  1017.     while ($row=Database::fetch_array($result))
  1018.     {
  1019.         if ($id=='')
  1020.         {
  1021.             $forum_categories_list[$row['cat_id']]=$row;
  1022.         }
  1023.         else
  1024.         {
  1025.             $forum_categories_list=$row;
  1026.         }
  1027.     }
  1028.     return $forum_categories_list;
  1029. }
  1030.  
  1031. /**
  1032. * This function retrieves all the fora in a given forum category
  1033. *
  1034. @param integer $cat_id the id of the forum category
  1035. @return an array containing all the information about the forums (regardless of their category)
  1036. *
  1037. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1038. @version february 2006, dokeos 1.8
  1039. */
  1040. function get_forums_in_category($cat_id)
  1041. {
  1042.     global $table_forums;
  1043.     global $table_item_property;
  1044.  
  1045.     $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1046.                 WHERE forum.forum_category='".Database::escape_string($cat_id)."'
  1047.                 AND forum.forum_id=item_properties.ref
  1048.                 AND item_properties.visibility=1
  1049.                 AND item_properties.tool='".TOOL_FORUM."'
  1050.                 ORDER BY forum.forum_order ASC";
  1051.     if (is_allowed_to_edit())
  1052.     {
  1053.         $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1054.                 WHERE forum.forum_category='".Database::escape_string($cat_id)."'
  1055.                 AND forum.forum_id=item_properties.ref
  1056.                 AND item_properties.visibility<>2
  1057.                 AND item_properties.tool='".TOOL_FORUM."'
  1058.                 ORDER BY forum_order ASC";
  1059.     }
  1060.     $result=api_sql_query($sql,__FILE__,__LINE__);
  1061.     while ($row=Database::fetch_array($result))
  1062.     {
  1063.         $forum_list[$row['forum_id']]=$row;
  1064.     }
  1065.     return $forum_list;
  1066. }
  1067. /**
  1068. * Retrieve all the forums (regardless of their category) or of only one. The forums are sorted according to the forum_order.
  1069. * Since it does not take the forum category into account there probably will be two or more forums that have forum_order=1, ...
  1070. *
  1071. @return an array containing all the information about the forums (regardless of their category)
  1072. @todo check $sql4 because this one really looks fishy.
  1073. *
  1074. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1075. @version february 2006, dokeos 1.8
  1076. */
  1077. function get_forums($id='')
  1078. {
  1079.     global $table_forums;
  1080.     global $table_threads;
  1081.     global $table_posts;
  1082.     global $table_item_property;
  1083.     global $table_users;
  1084.  
  1085.     // **************** GETTING ALL THE FORUMS ************************* //
  1086.     
  1087.     $session_condition = isset($_SESSION['id_session']'AND forum.session_id IN (0,'.intval($_SESSION['id_session']).')' '';
  1088.     $forum_list array();
  1089.     if ($id=='')
  1090.     {
  1091.         //-------------- Student -----------------//
  1092.         // select all the forum information of all forums (that are visible to students)
  1093.         $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1094.                     WHERE forum.forum_id=item_properties.ref
  1095.                     AND item_properties.visibility=1
  1096.                     AND item_properties.tool='".TOOL_FORUM."'
  1097.                     $session_condition
  1098.                     ORDER BY forum.forum_order ASC";
  1099.         // select the number of threads of the forums (only the threads that are visible)
  1100.         $sql2="SELECT count(*) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  1101.                         WHERE threads.thread_id=item_properties.ref
  1102.                         AND item_properties.visibility=1
  1103.                         AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1104.                         GROUP BY threads.forum_id";
  1105.         // select the number of posts of the forum (post that are visible and that are in a thread that is visible)
  1106.         $sql3="SELECT count(*) AS number_of_posts, posts.forum_id FROM $table_posts posts, $table_threads threads, ".$table_item_property." item_properties
  1107.                 WHERE posts.visible=1
  1108.                 AND posts.thread_id=threads.thread_id
  1109.                 AND threads.thread_id=item_properties.ref
  1110.                 AND item_properties.visibility=1
  1111.                 AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1112.                 GROUP BY threads.forum_id";
  1113.  
  1114.         //-------------- Course Admin  -----------------//
  1115.         if (is_allowed_to_edit())
  1116.         {
  1117.             // select all the forum information of all forums (that are not deleted)
  1118.             $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1119.                             WHERE forum.forum_id=item_properties.ref
  1120.                             AND item_properties.visibility<>2
  1121.                             AND item_properties.tool='".TOOL_FORUM."'
  1122.                             $session_condition
  1123.                             ORDER BY forum_order ASC";
  1124.             //echo $sql.'<hr>';
  1125.             // select the number of threads of the forums (only the threads that are not deleted)
  1126.             $sql2="SELECT count(*) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  1127.                             WHERE threads.thread_id=item_properties.ref
  1128.                             AND item_properties.visibility<>2
  1129.                             AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1130.                             GROUP BY threads.forum_id";
  1131.             //echo $sql2.'<hr>';
  1132.             // select the number of posts of the forum
  1133.             $sql3="SELECT count(*) AS number_of_posts, forum_id FROM $table_posts GROUP BY forum_id";
  1134.             //echo $sql3.'<hr>';
  1135.         }
  1136.  
  1137.  
  1138.     }
  1139.     // **************** GETTING ONE SPECIFIC FORUM ************************* //
  1140.     // We could do the splitup into student and course admin also but we want to have as much as information about a certain forum as possible
  1141.     // so we do not take too much information into account. This function (or this section of the function) is namely used to fill the forms
  1142.     // when editing a forum (and for the moment it is the only place where we use this part of the function)
  1143.     else
  1144.     {
  1145.         // select all the forum information of the given forum (that is not deleted)
  1146.         $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1147.                             WHERE forum.forum_id=item_properties.ref
  1148.                             AND forum_id='".Database::escape_string($id)."'
  1149.                             AND item_properties.visibility<>2
  1150.                             AND item_properties.tool='".TOOL_FORUM."'
  1151.                             $session_condition
  1152.                             ORDER BY forum_order ASC";
  1153.         // select the number of threads of the forum
  1154.         $sql2="SELECT count(*) AS number_of_threads, forum_id FROM $table_threads WHERE forum_id=".Database::escape_string($id)." GROUP BY forum_id";
  1155.         // select the number of posts of the forum
  1156.         $sql3="SELECT count(*) AS number_of_posts, forum_id FROM $table_posts WHERE forum_id=".Database::escape_string($id)." GROUP BY forum_id";
  1157.         // select the last post and the poster (note: this is probably no longer needed)
  1158.         $sql4="SELECT  post.post_id, post.forum_id, post.poster_id, post.poster_name, post.post_date, users.lastname, users.firstname
  1159.                     FROM $table_posts post, $table_users users
  1160.                     WHERE forum_id=".Database::escape_string($id)."
  1161.                     AND post.poster_id=users.user_id
  1162.                     GROUP BY post.forum_id
  1163.                     ORDER BY post.post_id ASC";
  1164.     }
  1165.     // handling all the forum information
  1166.     $result=api_sql_query($sql,__FILE__,__LINE__);
  1167.     while ($row=Database::fetch_array($result))
  1168.     {
  1169.         if ($id=='')
  1170.         {
  1171.             $forum_list[$row['forum_id']]=$row;
  1172.         }
  1173.         else
  1174.         {
  1175.             $forum_list=$row;
  1176.         }
  1177.     }
  1178.  
  1179.     // handling the threadcount information
  1180.     $result2=api_sql_query($sql2,__FILE__,__LINE__);
  1181.     while ($row2=Database::fetch_array($result2))
  1182.     {
  1183.         if ($id=='')
  1184.         {
  1185.             $forum_list[$row2['forum_id']]['number_of_threads']=$row2['number_of_threads'];
  1186.         }
  1187.         else
  1188.         {
  1189.             $forum_list['number_of_threads']=$row2['number_of_threads'];;
  1190.         }
  1191.     }
  1192.     // handling the postcount information
  1193.     $result3=api_sql_query($sql3,__FILE__,__LINE__);
  1194.     while ($row3=Database::fetch_array($result3))
  1195.     {
  1196.         if ($id=='')
  1197.         {
  1198.             if (array_key_exists($row3['forum_id'],$forum_list)) // this is needed because sql3 takes also the deleted forums into account
  1199.             {
  1200.                 $forum_list[$row3['forum_id']]['number_of_posts']=$row3['number_of_posts'];
  1201.             }
  1202.         }
  1203.         else
  1204.         {
  1205.             $forum_list['number_of_posts']=$row3['number_of_posts'];
  1206.         }
  1207.     }
  1208.  
  1209.     // finding the last post information (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)
  1210.     if ($id=='')
  1211.     {
  1212.         if(is_array($forum_list))
  1213.         {
  1214.             foreach ($forum_list as $key=>$value)
  1215.             {
  1216.                 $last_post_info_of_forum=get_last_post_information($key,is_allowed_to_edit());
  1217.                 $forum_list[$key]['last_post_id']=$last_post_info_of_forum['last_post_id'];
  1218.                 $forum_list[$key]['last_poster_id']=$last_post_info_of_forum['last_poster_id'];
  1219.                 $forum_list[$key]['last_post_date']=$last_post_info_of_forum['last_post_date'];
  1220.                 $forum_list[$key]['last_poster_name']=$last_post_info_of_forum['last_poster_name'];
  1221.                 $forum_list[$key]['last_poster_lastname']=$last_post_info_of_forum['last_poster_lastname'];
  1222.                 $forum_list[$key]['last_poster_firstname']=$last_post_info_of_forum['last_poster_firstname'];
  1223.             }
  1224.         }
  1225.         else
  1226.         {
  1227.             $forum_list array();
  1228.         }
  1229.     }
  1230.     else
  1231.     {
  1232.         $last_post_info_of_forum=get_last_post_information($id,is_allowed_to_edit());
  1233.         $forum_list['last_post_id']=$last_post_info_of_forum['last_post_id'];
  1234.         $forum_list['last_poster_id']=$last_post_info_of_forum['last_poster_id'];
  1235.         $forum_list['last_post_date']=$last_post_info_of_forum['last_post_date'];
  1236.         $forum_list['last_poster_name']=$last_post_info_of_forum['last_poster_name'];
  1237.         $forum_list['last_poster_lastname']=$last_post_info_of_forum['last_poster_lastname'];
  1238.         $forum_list['last_poster_firstname']=$last_post_info_of_forum['last_poster_firstname'];
  1239.     }
  1240.     return $forum_list;
  1241. }
  1242.  
  1243. /**
  1244. * This functions gets all the last post information of a certain forum
  1245. *
  1246. @param $forum_id the id of the forum we want to know the last post information of.
  1247. @param $show_invisibles 
  1248. @return array containing all the information about the last post (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)
  1249. *
  1250. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1251. @version february 2006, dokeos 1.8
  1252. */
  1253. function get_last_post_information($forum_id$show_invisibles=false)
  1254. {
  1255.     global $table_forums;
  1256.     global $table_threads;
  1257.     global $table_posts;
  1258.     global $table_item_property;
  1259.     global $table_users;
  1260.  
  1261.     $sql="SELECT post.post_id, post.forum_id, post.poster_id, post.poster_name, post.post_date, users.lastname, users.firstname, post.visible, thread_properties.visibility AS thread_visibility, forum_properties.visibility AS forum_visibility
  1262.                 FROM $table_posts post, $table_users users, $table_item_property thread_properties,  $table_item_property forum_properties
  1263.                 WHERE post.forum_id=".Database::escape_string($forum_id)."
  1264.                 AND post.poster_id=users.user_id
  1265.                 AND post.thread_id=thread_properties.ref
  1266.                 AND thread_properties.tool='".TOOL_FORUM_THREAD."'
  1267.                 AND post.forum_id=forum_properties.ref
  1268.                 AND forum_properties.tool='".TOOL_FORUM."'
  1269.                 ORDER BY post.post_id DESC";
  1270.     $result=api_sql_query($sql,__LINE__,__FILE__);
  1271.     if ($show_invisibles==true)
  1272.     {
  1273.         $row=Database::fetch_array($result);
  1274.         $return_array['last_post_id']=$row['post_id'];
  1275.         $return_array['last_poster_id']=$row['poster_id'];
  1276.         $return_array['last_post_date']=$row['post_date'];
  1277.         $return_array['last_poster_name']=$row['poster_name'];
  1278.         $return_array['last_poster_lastname']=$row['lastname'];
  1279.         $return_array['last_poster_firstname']=$row['firstname'];
  1280.         return $return_array;
  1281.     }
  1282.     else
  1283.     {
  1284.         // we have to loop through the results to find the first one that is actually visible to students (forum_category, forum, thread AND post are visible)
  1285.         while ($row=Database::fetch_array($result))
  1286.         {
  1287.             if ($row['visible']=='1' AND $row['thread_visibility']=='1' AND $row['forum_visibility']=='1')
  1288.             {
  1289.                 $return_array['last_post_id']=$row['post_id'];
  1290.                 $return_array['last_poster_id']=$row['poster_id'];
  1291.                 $return_array['last_post_date']=$row['post_date'];
  1292.                 $return_array['last_poster_name']=$row['poster_name'];
  1293.                 $return_array['last_poster_lastname']=$row['lastname'];
  1294.                 $return_array['last_poster_firstname']=$row['firstname'];
  1295.                 return $return_array;
  1296.             }
  1297.         }
  1298.     }
  1299. }
  1300.  
  1301. /**
  1302. * Retrieve all the threads of a given forum
  1303. *
  1304. @param 
  1305. @return an array containing all the information about the threads
  1306. *
  1307. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1308. @version february 2006, dokeos 1.8
  1309. */
  1310. function get_threads($forum_id)
  1311. {
  1312.     global $table_item_property;
  1313.     global $table_threads;
  1314.     global $table_posts;
  1315.     global $table_users;
  1316.  
  1317.     // important note:     it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
  1318.     //                    because we also have thread.* in it. This is because thread has a field locked and post also has the same field
  1319.     //                     since we are merging these we would have the post.locked value but in fact we want the thread.locked value
  1320.     //                    This is why it is added to the end of the field selection
  1321.  
  1322.     
  1323.     $sql "SELECT thread.*, item_properties.*, post.*, users.firstname, users.lastname, users.user_id,
  1324.                 last_poster_users.firstname as last_poster_firstname , last_poster_users.lastname as last_poster_lastname, last_poster_users.user_id as last_poster_user_id, thread.locked as locked
  1325.             FROM $table_threads thread
  1326.             INNER JOIN $table_item_property item_properties
  1327.                 ON thread.thread_id=item_properties.ref
  1328.                 AND item_properties.visibility='1'
  1329.                 AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1330.             LEFT JOIN $table_users users
  1331.                 ON thread.thread_poster_id=users.user_id
  1332.             LEFT JOIN $table_posts post
  1333.                 ON thread.thread_last_post = post.post_id
  1334.             LEFT JOIN $table_users last_poster_users
  1335.                 ON post.poster_id= last_poster_users.user_id
  1336.             WHERE thread.forum_id='".Database::escape_string($forum_id)."'
  1337.             ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
  1338.     if (is_allowed_to_edit())
  1339.     {
  1340.         // important note:     it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
  1341.         //                    because we also have thread.* in it. This is because thread has a field locked and post also has the same field
  1342.         //                     since we are merging these we would have the post.locked value but in fact we want the thread.locked value
  1343.         //                    This is why it is added to the end of the field selection
  1344.         $sql "SELECT thread.*, item_properties.*, post.*, users.firstname, users.lastname, users.user_id,
  1345.                     last_poster_users.firstname as last_poster_firstname , last_poster_users.lastname as last_poster_lastname, last_poster_users.user_id as last_poster_user_id, thread.locked as locked
  1346.                 FROM $table_threads thread
  1347.                 INNER JOIN $table_item_property item_properties
  1348.                     ON thread.thread_id=item_properties.ref
  1349.                     AND item_properties.visibility<>2
  1350.                     AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1351.                 LEFT JOIN $table_users users
  1352.                     ON thread.thread_poster_id=users.user_id
  1353.                 LEFT JOIN $table_posts post
  1354.                     ON thread.thread_last_post = post.post_id
  1355.                 LEFT JOIN $table_users last_poster_users
  1356.                     ON post.poster_id= last_poster_users.user_id
  1357.                 WHERE thread.forum_id='".Database::escape_string($forum_id)."'
  1358.                 ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
  1359.     }
  1360.     $result=api_sql_query($sql__FILE____LINE__);
  1361.     while ($row=Database::fetch_array($result,'ASSOC'))
  1362.     {
  1363.         $thread_list[]=$row;
  1364.     }
  1365.     return $thread_list;
  1366. }
  1367.  
  1368. /**
  1369. * Retrieve all posts of a given thread
  1370. *
  1371. @return an array containing all the information about the posts of a given thread
  1372. *
  1373. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1374. @version february 2006, dokeos 1.8
  1375. */
  1376. function get_posts($thread_id)
  1377. {
  1378.     global $table_posts;
  1379.     global $table_users;
  1380.  
  1381.     // note: change these SQL so that only the relevant fields of the user table are used
  1382.     if (api_is_allowed_to_edit())
  1383.     {
  1384.         $sql "SELECT * FROM $table_posts posts
  1385.                 LEFT JOIN  $table_users users
  1386.                     ON posts.poster_id=users.user_id
  1387.                 WHERE posts.thread_id='".Database::escape_string($thread_id)."'
  1388.                 ORDER BY posts.post_id ASC";
  1389.     }
  1390.     else
  1391.     {
  1392.         // students can only se the posts that are approved (posts.visible='1')
  1393.         $sql "SELECT * FROM $table_posts posts
  1394.                 LEFT JOIN  $table_users users
  1395.                     ON posts.poster_id=users.user_id
  1396.                 WHERE posts.thread_id='".Database::escape_string($thread_id)."'
  1397.                 AND posts.visible='1'
  1398.                 ORDER BY posts.post_id ASC";
  1399.     }
  1400.     $result=api_sql_query($sql__FILE____LINE__);
  1401.     while ($row=Database::fetch_array($result))
  1402.     {
  1403.         $post_list[]=$row;
  1404.     }
  1405.     return $post_list;
  1406. }
  1407.  
  1408. /**
  1409. * This function return the html syntax for the image
  1410. *
  1411. @param $image_url The url of the image (absolute or relative)
  1412. @param $alt The alt text (when the images cannot be displayed). http://www.w3.org/TR/html4/struct/objects.html#adef-alt
  1413. @param $title The title of the image. Most browsers display this as 'tool tip'. http://www.w3.org/TR/html4/struct/global.html#adef-title
  1414. *
  1415. @todo this is the same as the Display::xxx function, so it can be removed => all calls have to be changed also
  1416. *
  1417. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1418. @version february 2006, dokeos 1.8
  1419. */
  1420. function icon($image_url,$alt='',$title='')
  1421. {
  1422.     if ($title=='')
  1423.     {
  1424.         $title=$alt;
  1425.     }
  1426.     return '<img src="'.$image_url.'" alt="'.$alt.'" title="'.$title.'" />';
  1427. }
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434. /**************************************************************************
  1435.                     NEW TOPIC FUNCTIONS
  1436. **************************************************************************/
  1437.  
  1438. /**
  1439. * This function retrieves all the information of a post
  1440. *
  1441. @param $forum_id integer that indicates the forum
  1442. @return array returns
  1443. *
  1444. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1445. @version february 2006, dokeos 1.8
  1446. */
  1447. function get_post_information($post_id)
  1448. {
  1449.     global $table_posts;
  1450.     global $table_users;
  1451.  
  1452.     $sql="SELECT * FROM ".$table_posts."posts, ".$table_users." users WHERE posts.poster_id=users.user_id AND posts.post_id='".Database::escape_string($post_id)."'";
  1453.     $result=api_sql_query($sql__FILE____LINE__);
  1454.     $row=Database::fetch_array($result);
  1455.     return $row;
  1456. }
  1457.  
  1458.  
  1459. /**
  1460. * This function retrieves all the information of a thread
  1461. *
  1462. @param $forum_id integer that indicates the forum
  1463. @return array returns
  1464. *
  1465. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1466. @version february 2006, dokeos 1.8
  1467. */
  1468. function get_thread_information($thread_id)
  1469. {
  1470.     global $table_threads;
  1471.     global $table_item_property;
  1472.  
  1473.     $sql="SELECT * FROM ".$table_threads." threads, ".$table_item_property." item_properties
  1474.             WHERE item_properties.tool='".TOOL_FORUM_THREAD."'
  1475.             AND item_properties.ref='".Database::escape_string($thread_id)."'
  1476.             AND threads.thread_id='".Database::escape_string($thread_id)."'";
  1477.     $result=api_sql_query($sql__FILE____LINE__);
  1478.     $row=Database::fetch_array($result);
  1479.     return $row;
  1480. }
  1481.  
  1482.  
  1483. /**
  1484. * This function retrieves all the information of a given forum_id
  1485. *
  1486. @param $forum_id integer that indicates the forum
  1487. @return array returns
  1488. *
  1489. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1490. @version february 2006, dokeos 1.8
  1491. *
  1492. @deprecated this functionality is now moved to get_forums($forum_id)
  1493. */
  1494. function get_forum_information($forum_id)
  1495. {
  1496.     global $table_forums;
  1497.     global $table_item_property;
  1498.  
  1499.     $sql="SELECT * FROM ".$table_forums." forums, ".$table_item_property." item_properties
  1500.             WHERE item_properties.tool='".TOOL_FORUM."'
  1501.             AND item_properties.ref='".Database::escape_string($forum_id)."'
  1502.             AND forums.forum_id='".Database::escape_string($forum_id)."'";
  1503.     $result=api_sql_query($sql__FILE____LINE__);
  1504.     $row=Database::fetch_array($result);
  1505.     $row['approval_direct_post'0// we can't anymore change this option, so it should always be activated
  1506.     return $row;
  1507. }
  1508.  
  1509. /**
  1510. * This function retrieves all the information of a given forumcategory id
  1511. *
  1512. @param $forum_id integer that indicates the forum
  1513. @return array returns
  1514. *
  1515. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1516. @version february 2006, dokeos 1.8
  1517. */
  1518. {
  1519.     global $table_categories;
  1520.     global $table_item_property;
  1521.  
  1522.     $sql="SELECT * FROM ".$table_categories." forumcategories, ".$table_item_property." item_properties
  1523.             WHERE item_properties.tool='".TOOL_FORUM_CATEGORY."'
  1524.             AND item_properties.ref='".Database::escape_string($cat_id)."'
  1525.             AND forumcategories.cat_id='".Database::escape_string($cat_id)."'";
  1526.     $result=api_sql_query($sql__FILE____LINE__);
  1527.     $row=Database::fetch_array($result);
  1528.     return $row;
  1529. }
  1530.  
  1531. /**
  1532. * This function counts the number of forums inside a given category
  1533. *
  1534. @param $cat_id the id of the forum category
  1535. @todo an additional parameter that takes the visibility into account. For instance $countinvisible=0 would return the number
  1536. *          of visible forums, $countinvisible=1 would return the number of visible and invisible forums
  1537. @return int the number of forums inside the given category
  1538. *
  1539. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1540. @version february 2006, dokeos 1.8
  1541. */
  1542. {
  1543.     global $table_forums;
  1544.  
  1545.     $sql="SELECT count(*) AS number_of_forums FROM ".$table_forums." WHERE forum_category='".Database::escape_string($cat_id)."'";
  1546.     $result=api_sql_query($sql__FILE____LINE__);
  1547.     $row=Database::fetch_array($result);
  1548.     return $row['number_of_forums'];
  1549. }
  1550.  
  1551. /**
  1552. * This function stores a new thread. This is done through an entry in the forum_thread table AND
  1553. * in the forum_post table because. The threads are also stored in the item_property table. (forum posts are not (yet))
  1554. *
  1555. @param 
  1556. @return 
  1557. *
  1558. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1559. @version february 2006, dokeos 1.8
  1560. */
  1561. function store_thread($values)
  1562. {
  1563.     global $table_threads;
  1564.     global $table_posts;
  1565.     global $_user;
  1566.     global $_course;
  1567.     global $current_forum;
  1568.     global $origin;
  1569.     global $forum_table_attachment;
  1570.  
  1571.     $upload_ok=1;
  1572.     $has_attachment=false;
  1573.         
  1574.     if(!empty($_FILES['user_upload']['name']))
  1575.     {
  1576.         $upload_ok process_uploaded_file($_FILES['user_upload']);
  1577.         $has_attachment=true;
  1578.     }
  1579.     
  1580.         
  1581.     if($upload_ok)
  1582.     {        
  1583.     
  1584.         $post_date=date('Y-m-d H:i:s');
  1585.     
  1586.         if ($current_forum['approval_direct_post']=='1' AND !api_is_allowed_to_edit())
  1587.         {
  1588.             $visible=0// the post is not approved yet.
  1589.         }
  1590.         else
  1591.         {
  1592.             $visible=1;
  1593.         }
  1594.         
  1595.         $clean_post_title=Security::remove_XSS(Database::escape_string(htmlspecialchars($values['post_title'])));
  1596.         
  1597.         // We first store an entry in the forum_thread table because the thread_id is used in the forum_post table
  1598.         $sql="INSERT INTO $table_threads (thread_title, forum_id, thread_poster_id, thread_poster_name, thread_date, thread_sticky)
  1599.                 VALUES ('".$clean_post_title."',
  1600.                         '".Database::escape_string($values['forum_id'])."',
  1601.                         '".Database::escape_string($_user['user_id'])."',
  1602.                         '".Database::escape_string($values['poster_name'])."',
  1603.                         '".Database::escape_string($post_date)."',
  1604.                         '".Database::escape_string($values['thread_sticky'])."')";
  1605.         $result=api_sql_query($sql__LINE____FILE__);
  1606.         $last_thread_id=Database::insert_id();
  1607.                 
  1608.         api_item_property_update($_courseTOOL_FORUM_THREAD$last_thread_id,"ForumThreadAdded"api_get_user_id());
  1609.         // if the forum properties tell that the posts have to be approved we have to put the whole thread invisible
  1610.         // because otherwise the students will see the thread and not the post in the thread.
  1611.         // we also have to change $visible because the post itself has to be visible in this case (otherwise the teacher would have
  1612.         // to make the thread visible AND the post
  1613.         
  1614.         if ($visible==0)
  1615.         {
  1616.             api_item_property_update($_courseTOOL_FORUM_THREAD$last_thread_id,"invisible"api_get_user_id());
  1617.             $visible=1;
  1618.         }
  1619.     
  1620.     
  1621.         // We now store the content in the table_post table
  1622.         $sql="INSERT INTO $table_posts (post_title, post_text, thread_id, forum_id, poster_id, poster_name, post_date, post_notification, post_parent_id, visible)
  1623.                 VALUES ('".$clean_post_title."',
  1624.                 '".Database::escape_string($values['post_text'])."',
  1625.                 '".Database::escape_string($last_thread_id)."',
  1626.                 '".Database::escape_string($values['forum_id'])."',
  1627.                 '".Database::escape_string($_user['user_id'])."',
  1628.                 '".Database::escape_string($values['poster_name'])."',
  1629.                 '".Database::escape_string($post_date)."',
  1630.                 '".Database::escape_string($values['post_notification'])."','0',
  1631.                 '".Database::escape_string($visible)."')";
  1632.         api_sql_query($sql__LINE____FILE__);
  1633.         $last_post_id=Database::insert_id();
  1634.                 
  1635.         // now have to update the thread table to fill the thread_last_post field (so that we know when the thread has been updated for the last time)
  1636.         $sql="UPDATE $table_threads SET thread_last_post='".Database::escape_string($last_post_id)."'  WHERE thread_id='".Database::escape_string($last_thread_id)."'";
  1637.         $result=api_sql_query($sql__LINE____FILE__);
  1638.     
  1639.         $message=get_lang('NewThreadStored');
  1640.         
  1641.         
  1642.         // Storing the attachments if any
  1643.         if ($has_attachment)
  1644.         {            
  1645.             $courseDir   $_course['path'].'/upload/forum';
  1646.             $sys_course_path api_get_path(SYS_COURSE_PATH);        
  1647.             $updir $sys_course_path.$courseDir;
  1648.                         
  1649.             // Try to add an extension to the file if it hasn't one
  1650.             $new_file_name add_ext_on_mime(stripslashes($_FILES['user_upload']['name'])$_FILES['user_upload']['type']);    
  1651.         
  1652.             // user's file name
  1653.             $file_name =$_FILES['user_upload']['name'];
  1654.                         
  1655.             if (!filter_extension($new_file_name)) 
  1656.             {
  1657.                 Display :: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));                
  1658.             }
  1659.             else
  1660.             {
  1661.                 $new_file_name uniqid('');                        
  1662.                 $new_path=$updir.'/'.$new_file_name;
  1663.                 $result@move_uploaded_file($_FILES['user_upload']['tmp_name']$new_path);
  1664.                 $comment=$values['file_comment'];                
  1665.                                 
  1666.                 // Storing the attachments if any
  1667.                 if ($result)
  1668.                 {                    
  1669.                     $sql='INSERT INTO '.$forum_table_attachment.'(filename,comment, path, post_id,size) '.
  1670.                          "VALUES ( '".Database::escape_string($file_name)."', '".Database::escape_string($comment)."', '".Database::escape_string($new_file_name)."' , '".$last_post_id."', '".$_FILES['user_upload']['size']."' )";                        
  1671.                     $result=api_sql_query($sql__LINE____FILE__);                    
  1672.                     $message.=' / '.get_lang('FileUploadSucces').'<br />';
  1673.                     
  1674.                     $last_id=Database::insert_id();
  1675.                     api_item_property_update($_courseTOOL_FORUM_ATTACH$last_id ,'ForumAttachmentAdded'api_get_user_id());
  1676.                                 
  1677.                 }            
  1678.             }             
  1679.         }
  1680.         else
  1681.         {
  1682.             $message.='<br />';
  1683.         }
  1684.  
  1685.         if ($current_forum['approval_direct_post']=='1' AND !api_is_allowed_to_edit())
  1686.         {
  1687.             $message.=get_lang('MessageHasToBeApproved').'<br />';
  1688.             $message.=get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'">'.get_lang('Forum').'</a><br />';
  1689.         }
  1690.         else
  1691.         {
  1692.             $message.=get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&origin='.$origin.'">'.get_lang('Forum').'</a><br />';
  1693.             $message.=get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&origin='.$origin.'&amp;thread='.$last_thread_id.'">'.get_lang('Message').'</a>';
  1694.         }
  1695.         $reply_info['new_post_id'$last_post_id;
  1696.  
  1697.         if ($values['post_notification'== 1)
  1698.         {
  1699.             set_notification('thread',$last_thread_idtrue);
  1700.         }        
  1701.         
  1702.         send_notification_mails($last_thread_id,$reply_info);
  1703.     
  1704.         session_unregister('formelements');
  1705.         session_unregister('origin');
  1706.         session_unregister('breadcrumbs');
  1707.         session_unregister('addedresource');
  1708.         session_unregister('addedresourceid');
  1709.     
  1710.         Display :: display_confirmation_message($message,false);
  1711.     }
  1712.     else
  1713.     {
  1714.         Display::display_error_message(get_lang('UplNoFileUploaded'));            
  1715.     }
  1716. }
  1717. /**
  1718. * This function displays the form that is used to add a post. This can be a new thread or a reply.
  1719. @param $action is the parameter that determines if we are
  1720. *                     1. newthread: adding a new thread (both empty) => No I-frame
  1721. *                     2. replythread: Replying to a thread ($action = replythread) => I-frame with the complete thread (if enabled)
  1722. *                     3. replymessage: Replying to a message ($action =replymessage) => I-frame with the complete thread (if enabled) (I first thought to put and I-frame with the message only)
  1723. *                      4. quote: Quoting a message ($action= quotemessage) => I-frame with the complete thread (if enabled). The message will be in the reply. (I first thought not to put an I-frame here)
  1724. *
  1725. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1726. @version february 2006, dokeos 1.8
  1727. */
  1728. function show_add_post_form($action=''$id=''$form_values='')
  1729. {
  1730.     global $forum_setting;
  1731.     global $current_forum;
  1732.     global $_user;
  1733.     global $origin;
  1734.     global $charset
  1735.  
  1736.     // initiate the object
  1737.     $form new FormValidator('thread''post'api_get_self().'?forum='.Security::remove_XSS($_GET['forum']).'&thread='.Security::remove_XSS($_GET['thread']).'&post='.Security::remove_XSS($_GET['post']).'&action='.Security::remove_XSS($_GET['action']).'&origin='.$origin);
  1738.     $form->setConstants(array('forum' => '5'));
  1739.  
  1740.     // settting the form elements
  1741.     $form->addElement('hidden''forum_id'strval(intval($_GET['forum'])));
  1742.     $form->addElement('hidden''thread_id'strval(intval($_GET['thread'])));
  1743.  
  1744.     // if anonymous posts are allowed we also display a form to allow the user to put his name or username in
  1745.     if ($current_forum['allow_anonymous']==AND !isset($_user['user_id']))
  1746.     {
  1747.         $form->addElement('text''poster_name'get_lang('Name'));
  1748.     }
  1749.  
  1750.     $form->addElement('text''post_title'get_lang('Title'),'class="input_titles"');
  1751.     $form->addElement('html_editor''post_text'get_lang('Text'));
  1752.  
  1753.     if ($forum_setting['allow_post_notificiation'AND isset($_user['user_id']))
  1754.     {
  1755.         $form->addElement('checkbox''post_notification'''get_lang('NotifyByEmail').' ('.$_user['mail'].')');
  1756.     }
  1757.  
  1758.     if ($forum_setting['allow_sticky'AND api_is_allowed_to_edit(AND $action=='newthread')
  1759.     {
  1760.         $form->addElement('checkbox''thread_sticky'''get_lang('StickyPost'));
  1761.     }
  1762.  
  1763.     if ($current_forum['allow_attachments']=='1' OR api_is_allowed_to_edit())
  1764.     {
  1765.         //$form->add_resource_button();
  1766.         $values $form->exportValues();
  1767.     }
  1768.     
  1769.     // user upload
  1770.     $form->addElement('html','<br /><b><div class="row"><div class="label">'.get_lang('AddAnAttachment').'</div></div></b><br /><br />');
  1771.     $form->addElement('file','user_upload',ucwords(get_lang('FileName')),'');        
  1772.     $form->addElement('textarea','file_comment',get_lang('FileComment'),array ('rows' => 4'cols' => 34));
  1773.     
  1774.     $form->addElement('submit''SubmitPost'get_lang('Ok'));    
  1775.     $form->add_real_progress_bar('DocumentUpload','user_upload');
  1776.     
  1777.  
  1778.     
  1779.  
  1780.     if (!empty($form_values))
  1781.     {
  1782.         $defaults['post_title']=prepare4display(Security::remove_XSS($form_values['post_title']));
  1783.         $defaults['post_text']=prepare4display(Security::remove_XSS($form_values['post_text']));
  1784.         $defaults['post_notification']=Security::remove_XSS($form_values['post_notification']);
  1785.         $defaults['thread_sticky']=Security::remove_XSS($form_values['thread_sticky']);
  1786.     }
  1787.  
  1788.     // if we are quoting a message we have to retrieve the information of the post we are quoting so that
  1789.     // we can add this as default to the textarea
  1790.     if (($action=='quote' OR $action=='replymessage'and isset($_GET['post']))
  1791.     {
  1792.         // we also need to put the parent_id of the post in a hidden form when we are quoting or replying to a message (<> reply to a thread !!!)
  1793.         $form->addElement('hidden''post_parent_id'strval(intval($_GET['post'])))// note this has to be cleaned first
  1794.  
  1795.         // if we are replying or are quoting then we display a default title.
  1796.          $values=get_post_information($_GET['post'])// note: this has to be cleaned first
  1797.         $defaults['post_title']=get_lang('ReplyShort').html_entity_decode($values['post_title'],ENT_QUOTES,$charset);
  1798.         // When we are quoting a message then we have to put that message into the wysiwyg editor.
  1799.         // note: the style has to be hardcoded here because using class="quote" didn't work
  1800.         if($action=='quote')
  1801.         {
  1802.             $defaults['post_text']='<div>&nbsp;</div><div style="margin: 5px;"><div style="font-size: 90%;    font-style: italic;">'.get_lang('Quoting').' '.$values['firstname'].' '.$values['lastname'].':</div><div style="color: #006600; font-size: 90%;    font-style: italic; background-color: #FAFAFA; border: #D1D7DC 1px solid; padding: 3px;">'.prepare4display($values['post_text']).'</div></div><div>&nbsp;</div><div>&nbsp;</div>';
  1803.         }
  1804.     }
  1805.     $form->setDefaults($defaults);
  1806.  
  1807.     // the course admin can make a thread sticky (=appears with special icon and always on top)
  1808.     $form->addRule('post_title''<div class="required">'.get_lang('ThisFieldIsRequired')'required');
  1809.     if ($current_forum['allow_anonymous']==AND !isset($_user['user_id']))
  1810.     {
  1811.         $form->addRule('poster_name''<div class="required">'.get_lang('ThisFieldIsRequired')'required');
  1812.     }
  1813.  
  1814.     // The validation or display
  1815.     if$form->validate() )
  1816.     {
  1817.        $values $form->exportValues();
  1818.        return $values;
  1819.     }
  1820.     else
  1821.     {
  1822.         $form->display();
  1823.         echo '<br />';
  1824.         if ($forum_setting['show_thread_iframe_on_reply'and $action<>'newthread')
  1825.         {
  1826.             echo "<iframe src=\"iframe_thread.php?forum=".Security::remove_XSS($_GET['forum'])."&amp;thread=".Security::remove_XSS($_GET['thread'])."#".Security::remove_XSS($_GET['post'])."\" width=\"80%\"></iframe>";
  1827.         }
  1828.     }
  1829. }
  1830.  
  1831.  
  1832. /**
  1833. * This function stores a reply in the forum_post table.
  1834. * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date)
  1835. *
  1836. @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1837. @version february 2006, dokeos 1.8
  1838. */
  1839. function store_reply($values)
  1840. {
  1841.     global $table_threads;
  1842.     global $table_posts;
  1843.     global $forum_table_attachment;
  1844.     global $_user;
  1845.     global $_course;
  1846.     global $current_forum;
  1847.     global $origin;
  1848.  
  1849.     $post_date=date('Y-m-d H:i:s');
  1850.     if ($current_forum['approval_direct_post']=='1' AND !api_is_allowed_to_edit())
  1851.     {
  1852.         $visible=0// the post is not approved yet.
  1853.     }
  1854.     else
  1855.     {
  1856.         $visible=1;
  1857.     }
  1858.     
  1859.     $upload_ok=1;
  1860.     $has_attachment=false;    
  1861.     if(!empty($_FILES['user_upload']['name']))
  1862.     {
  1863.         $upload_ok process_uploaded_file($_FILES['user_upload']);
  1864.         $has_attachment=true;
  1865.     }
  1866.     
  1867.     if($upload_ok)
  1868.     {
  1869.         // We first store an entry in the forum_post table
  1870.         $sql="INSERT INTO $table_posts (post_title, post_text, thread_id, forum_id, poster_id, post_date, post_notification, post_parent_id, visible)
  1871.                 VALUES ('".Database::escape_string($values['post_title'])."',
  1872.                     &n