forumfunction.inc.php 149 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621
  1. <?php
  2. /*
  3. ==============================================================================
  4. Dokeos - elearning and course management software
  5. Copyright (c) 2004-2008 Dokeos SPRL
  6. Copyright (c) 2003 Ghent University (UGent)
  7. Copyright (c) 2001 Universite catholique de Louvain (UCL)
  8. Copyright (c) various contributors
  9. For a full list of contributors, see "credits.txt".
  10. The full license can be read in "license.txt".
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License
  13. as published by the Free Software Foundation; either version 2
  14. of the License, or (at your option) any later version.
  15. See the GNU General Public License for more details.
  16. Contact address: Dokeos, rue du Corbeau, 108, B-1030 Brussels, Belgium
  17. Mail: info@dokeos.com
  18. ==============================================================================
  19. */
  20. /**
  21. * These files are a complete rework of the forum. The database structure is
  22. * based on phpBB but all the code is rewritten. A lot of new functionalities
  23. * are added:
  24. * - forum categories and forums can be sorted up or down, locked or made invisible
  25. * - consistent and integrated forum administration
  26. * - forum options: are students allowed to edit their post?
  27. * moderation of posts (approval)
  28. * reply only forums (students cannot create new threads)
  29. * multiple forums per group
  30. * - sticky messages
  31. * - new view option: nested view
  32. * - quoting a message
  33. *
  34. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  35. * @copyright Ghent University
  36. * @copyright Patrick Cool
  37. * @author Julio Montoya <gugli100@gmail.com>, Dokeos Several fixes
  38. * @package dokeos.forum
  39. *
  40. * @todo several functions have to be moved to the itemmanager library
  41. * @todo displaying icons => display library
  42. * @todo complete the missing phpdoc the correct order should be
  43. *
  44. * some explanation of the function
  45. *
  46. * @param
  47. * @return
  48. *
  49. @todo
  50. *
  51. * @author firstname lastname <email>, organisation
  52. * @version (day) month year
  53. *
  54. * @deprecated
  55. */
  56. /**
  57. **************************************************************************
  58. * IMPORTANT NOTICE
  59. * Please do not change anything is this code yet because there are still
  60. * some significant code that need to happen and I do not have the time to
  61. * merge files and test it all over again. So for the moment, please do not
  62. * touch the code
  63. * -- Patrick Cool <patrick.cool@UGent.be>
  64. **************************************************************************
  65. */
  66. require_once(api_get_path(INCLUDE_PATH).'/lib/mail.lib.inc.php');
  67. require_once(api_get_path(INCLUDE_PATH).'/conf/mail.conf.php');
  68. require_once(api_get_path(INCLUDE_PATH).'/lib/usermanager.lib.php');
  69. get_notifications_of_user();
  70. /**
  71. * This function handles all the forum and forumcategories actions. This is a wrapper for the
  72. * forum and forum categories. All this code code could go into the section where this function is
  73. * called but this make the code there cleaner.
  74. * @param
  75. * @return
  76. *
  77. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  78. * @version february 2006, dokeos 1.8
  79. */
  80. function handle_forum_and_forumcategories() {
  81. $action_forum_cat = isset($_GET['action']) ? $_GET['action'] : '';
  82. $post_submit_cat= isset($_POST['SubmitForumCategory']) ? $_POST['SubmitForumCategory'] : '';
  83. $post_submit_forum= isset($_POST['SubmitForum']) ? $_POST['SubmitForum'] : '';
  84. $get_id=isset($_GET['id']) ? $_GET['id'] : '';
  85. // Adding a forum category
  86. if (($action_forum_cat=='add' && $_GET['content']=='forumcategory') || $post_submit_cat ) {
  87. show_add_forumcategory_form();
  88. }
  89. // Adding a forum
  90. if ((($action_forum_cat=='add' || $action_forum_cat=='edit') && $_GET['content']=='forum') || $post_submit_forum ) {
  91. if ($action_forum_cat=='edit' && $get_id || $post_submit_forum ) {
  92. $inputvalues=get_forums(strval(intval($get_id))); // note: this has to be cleaned first
  93. } else {
  94. $inputvalues='';
  95. }
  96. show_add_forum_form($inputvalues);
  97. }
  98. // Edit a forum category
  99. if (($action_forum_cat=='edit' && $_GET['content']=='forumcategory' && isset($_GET['id'])) || $_POST['SubmitEditForumCategory'] )
  100. {
  101. $forum_category=get_forum_categories(strval(intval($_GET['id']))); // note: this has to be cleaned first
  102. show_edit_forumcategory_form($forum_category);
  103. }
  104. // Delete a forum category
  105. if (( isset($_GET['action']) && $_GET['action']=='delete') && isset($_GET['content']) && $get_id) {
  106. $id_forum=Security::remove_XSS($get_id);
  107. $list_threads=get_threads($id_forum);
  108. for ( $i=0; $i < count($list_threads); $i++ ) {
  109. $messaje=delete_forum_forumcategory_thread('thread',$list_threads[$i]['thread_id']);
  110. $table_link = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
  111. $sql_link='DELETE FROM '.$table_link.' WHERE ref_id='.$list_threads[$i]['thread_id'].' and type=5 and course_code="'.api_get_course_id().'";';
  112. api_sql_query($sql_link,__FILE__,__LINE__);
  113. }
  114. $return_message=delete_forum_forumcategory_thread($_GET['content'],$_GET['id']);
  115. Display :: display_confirmation_message($return_message,false);
  116. }
  117. // Change visibility of a forum or a forum category
  118. if (($action_forum_cat=='invisible' || $action_forum_cat=='visible') && isset($_GET['content']) && isset($_GET['id'])) {
  119. $return_message=change_visibility($_GET['content'], $_GET['id'],$_GET['action']);// note: this has to be cleaned first
  120. Display :: display_confirmation_message($return_message,false);
  121. }
  122. // Change lock status of a forum or a forum category
  123. if (($action_forum_cat=='lock' || $action_forum_cat=='unlock') && isset($_GET['content']) && isset($_GET['id'])) {
  124. $return_message=change_lock_status($_GET['content'], $_GET['id'],$_GET['action']);// note: this has to be cleaned first
  125. Display :: display_confirmation_message($return_message,false);
  126. }
  127. // Move a forum or a forum category
  128. if ($action_forum_cat=='move' && isset($_GET['content']) && isset($_GET['id']) && isset($_GET['direction'])) {
  129. $return_message=move_up_down($_GET['content'], $_GET['direction'], $_GET['id']);// note: this has to be cleaned first
  130. Display :: display_confirmation_message($return_message,false);
  131. }
  132. }
  133. /**
  134. * This function displays the form that is used to add a forum category.
  135. *
  136. * @param
  137. * @return
  138. *
  139. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  140. * @version february 2006, dokeos 1.8
  141. */
  142. function show_add_forumcategory_form($inputvalues=array()) {
  143. // initiate the object
  144. $form = new FormValidator('forumcategory','post');
  145. // settting the form elements
  146. $form->addElement('header', '', get_lang('AddForumCategory'));
  147. $form->addElement('text', 'forum_category_title', get_lang('Title'),'class="input_titles"');
  148. $form->addElement('html_editor', 'forum_category_comment', get_lang('Comment'));
  149. $form->addElement('submit', 'SubmitForumCategory', get_lang('Ok'));
  150. // setting the rules
  151. $form->addRule('forum_category_title', '<div class="required">'.get_lang('ThisFieldIsRequired'), 'required');
  152. // The validation or display
  153. if ( $form->validate() ) {
  154. $check = Security::check_token('post');
  155. if ($check) {
  156. $values = $form->exportValues();
  157. store_forumcategory($values);
  158. }
  159. Security::clear_token();
  160. } else {
  161. $token = Security::get_token();
  162. $form->addElement('hidden','sec_token');
  163. $form->setConstants(array('sec_token' => $token));
  164. $form->display();
  165. }
  166. }
  167. /**
  168. * This function displays the form that is used to add a forum category.
  169. *
  170. * @param
  171. * @return
  172. *
  173. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  174. * @version february 2006, dokeos 1.8
  175. */
  176. function show_add_forum_form($inputvalues=array()) {
  177. global $_course;
  178. // initiate the object
  179. $form = new FormValidator('forumcategory', 'post', 'index.php');
  180. // the header for the form
  181. $session_header = isset($_SESSION['session_name']) ? ' ('.$_SESSION['session_name'].') ' : '';
  182. $form->addElement('header', '', get_lang('AddForum').$session_header);
  183. // we have a hidden field if we are editing
  184. if (is_array($inputvalues)) {
  185. $my_forum_id=isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
  186. $form->addElement('hidden', 'forum_id', $my_forum_id);
  187. }
  188. // The title of the forum
  189. $form->addElement('text', 'forum_title', get_lang('Title'),'class="input_titles"');
  190. // The comment of the forum
  191. $form->addElement('html_editor', 'forum_comment', get_lang('Comment'));
  192. // dropdown list: Forum Categories
  193. $forum_categories=get_forum_categories();
  194. foreach ($forum_categories as $key=>$value) {
  195. $forum_categories_titles[$value['cat_id']]=$value['cat_title'];
  196. }
  197. $form->addElement('select', 'forum_category', get_lang('InForumCategory'), $forum_categories_titles);
  198. if ($_course['visibility']==COURSE_VISIBILITY_OPEN_WORLD) {
  199. // This is for vertical
  200. //$form->addElement('radio', 'allow_anonymous', get_lang('AllowAnonymousPosts'), get_lang('Yes'), 1);
  201. //$form->addElement('radio', 'allow_anonymous', '', get_lang('No'), 0);
  202. // This is for horizontal
  203. $group='';
  204. $group[] =& HTML_QuickForm::createElement('radio', 'allow_anonymous',null,get_lang('Yes'),1);
  205. $group[] =& HTML_QuickForm::createElement('radio', 'allow_anonymous',null,get_lang('No'),0);
  206. $form->addGroup($group, 'allow_anonymous_group', get_lang('AllowAnonymousPosts'), '&nbsp;');
  207. }
  208. // This is for vertical
  209. //$form->addElement('radio', 'students_can_edit', get_lang('StudentsCanEdit'), get_lang('Yes'), 1);
  210. //$form->addElement('radio', 'students_can_edit', '', get_lang('No'), 0);
  211. // This is for horizontal
  212. /* if (document.getElementById('id_qualify').style.display == 'none') {
  213. document.getElementById('id_qualify').style.display = 'block';
  214. document.getElementById('plus').innerHTML='&nbsp;<img src=\"../img/nolines_minus.gif\" alt=\"\" />&nbsp;".get_lang('AddAnAttachment')."';
  215. } else {
  216. document.getElementById('options').style.display = 'none';
  217. document.getElementById('plus').innerHTML='&nbsp;<img src=\"../img/nolines_plus.gif\" alt=\"\" />&nbsp;".get_lang('AddAnAttachment')."';
  218. }*/
  219. $form->addElement('static','Group','<div id="plus"><a href="javascript://" onclick="advanced_parameters()" ><br /><span id="plus_minus">&nbsp;<img src="../img/nolines_plus.gif" alt="" />&nbsp;'.get_lang('AdvancedParameters').'</span></a></div>');
  220. $form->addElement('html','<div id="options" style="display:none">');
  221. $group='';
  222. $group[] =& HTML_QuickForm::createElement('radio', 'students_can_edit',null,get_lang('Yes'),1);
  223. $group[] =& HTML_QuickForm::createElement('radio', 'students_can_edit',null,get_lang('No'),0);
  224. $form->addGroup($group, 'students_can_edit_group', get_lang('StudentsCanEdit'), '&nbsp;');
  225. // This is for vertical
  226. //$form->addElement('radio', 'approval_direct', get_lang('ApprovalDirect'), get_lang('Approval'), 1);
  227. //$form->addElement('radio', 'approval_direct', '', get_lang('Direct'), 0);
  228. // This is for horizontal
  229. $group='';
  230. $group[] =& HTML_QuickForm::createElement('radio', 'approval_direct',null,get_lang('Approval'),1);
  231. $group[] =& HTML_QuickForm::createElement('radio', 'approval_direct',null,get_lang('Direct'),0);
  232. //$form->addGroup($group, 'approval_direct_group', get_lang('ApprovalDirect'), '&nbsp;');
  233. // This is for vertical
  234. //$form->addElement('radio', 'allow_attachments', get_lang('AllowAttachments'), get_lang('Yes'), 1);
  235. //$form->addElement('radio', 'allow_attachments', '', get_lang('No'), 0);
  236. // This is for horizontal
  237. $group='';
  238. $group[] =& HTML_QuickForm::createElement('radio', 'allow_attachments',null,get_lang('Yes'),1);
  239. $group[] =& HTML_QuickForm::createElement('radio', 'allow_attachments',null,get_lang('No'),0);
  240. //$form->addGroup($group, 'allow_attachments_group', get_lang('AllowAttachments'), '&nbsp;');
  241. // This is for vertical
  242. //$form->addElement('radio', 'allow_new_threads', get_lang('AllowNewThreads'), 1, get_lang('Yes'));
  243. //$form->addElement('radio', 'allow_new_threads', '', 0, get_lang('No'));
  244. // This is for horizontal
  245. $group='';
  246. $group[] =& HTML_QuickForm::createElement('radio', 'allow_new_threads',null, get_lang('Yes'),1);
  247. $group[] =& HTML_QuickForm::createElement('radio', 'allow_new_threads',null, get_lang('No'),0);
  248. $form->addGroup($group, 'allow_new_threads_group', get_lang('AllowNewThreads'), '&nbsp;');
  249. $group='';
  250. $group[] =& HTML_QuickForm::createElement('radio', 'default_view_type', null, get_lang('Flat'), 'flat');
  251. $group[] =& HTML_QuickForm::createElement('radio', 'default_view_type', null, get_lang('Threaded'), 'threaded');
  252. $group[] =& HTML_QuickForm::createElement('radio', 'default_view_type', null, get_lang('Nested'), 'nested');
  253. $form->addGroup($group, 'default_view_type_group', get_lang('DefaultViewType'), '&nbsp;');
  254. $form->addElement('static','Group', '<br /><strong>'.get_lang('GroupSettings').'</strong>');
  255. // dropdown list: Groups
  256. $groups=GroupManager::get_group_list();
  257. $groups_titles[0]=get_lang('NotAGroupForum');
  258. foreach ($groups as $key=>$value) {
  259. $groups_titles[$value['id']]=$value['name'];
  260. }
  261. $form->addElement('select', 'group_forum', get_lang('ForGroup'), $groups_titles);
  262. // Public or private group forum
  263. $group='';
  264. $group[] =& HTML_QuickForm::createElement('radio', 'public_private_group_forum', null, get_lang('Public'), 'public');
  265. $group[] =& HTML_QuickForm::createElement('radio', 'public_private_group_forum', null, get_lang('Private'), 'private');
  266. $form->addGroup($group, 'public_private_group_forum_group', get_lang('PublicPrivateGroupForum'), '&nbsp;');
  267. // Forum image
  268. $form->add_progress_bar();
  269. if (isset($inputvalues['forum_image']) && strlen($inputvalues['forum_image']) > 0) {
  270. $image_path = api_get_path(WEB_COURSE_PATH).api_get_course_path().'/upload/forum/images/'.$inputvalues['forum_image'];
  271. $image_size = @getimagesize($image_path);
  272. $img_attributes = '';
  273. if (!empty($image_size)) {
  274. if ($image_size[0] > 100 || $image_size[1] > 100) {
  275. //limit display width and height to 100px
  276. $img_attributes = 'width="100" height="100"';
  277. }
  278. $show_preview_image='<img src="'.$image_path.'" '.$img_attributes.'>';
  279. $div = '<div class="row">
  280. <div class="label">'.get_lang('PreviewImage').'</div>
  281. <div class="formw">
  282. '.$show_preview_image.'
  283. </div>
  284. </div>';
  285. $form->addElement('html', $div .'<br/>');
  286. $form->addElement('checkbox', 'remove_picture', null, get_lang('DelImage'));
  287. }
  288. }
  289. $forum_image=isset($inputvalues['forum_image']) ? $inputvalues['forum_image'] : '';
  290. $form->addElement('file', 'picture', ($forum_image != '' ? get_lang('UpdateImage') : get_lang('AddImage')));
  291. $form->addRule('picture', get_lang('OnlyImagesAllowed'), 'mimetype', array('image/gif', 'image/jpeg', 'image/png'));
  292. $form->addElement('html','</div>');
  293. // The OK button
  294. $form->addElement('submit', 'SubmitForum', get_lang('Ok'));
  295. // setting the rules
  296. $form->addRule('forum_title', get_lang('ThisFieldIsRequired'), 'required');
  297. $form->addRule('forum_category', get_lang('ThisFieldIsRequired'), 'required');
  298. global $charset;
  299. // settings the defaults
  300. if (!is_array($inputvalues)) {
  301. $defaults['allow_anonymous_group']['allow_anonymous']=0;
  302. $defaults['students_can_edit_group']['students_can_edit']=0;
  303. $defaults['approval_direct_group']['approval_direct']=0;
  304. $defaults['allow_attachments_group']['allow_attachments']=1;
  305. $defaults['allow_new_threads_group']['allow_new_threads']=0;
  306. $defaults['default_view_type_group']['default_view_type']=api_get_setting('default_forum_view');
  307. $defaults['public_private_group_forum_group']['public_private_group_forum']='public';
  308. if (isset($_GET['forumcategory'])) {
  309. $defaults['forum_category']=Security::remove_XSS($_GET['forumcategory']);
  310. }
  311. } else { // the default values when editing = the data in the table
  312. $defaults['forum_id']=isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
  313. $defaults['forum_title']=prepare4display(html_entity_decode(isset($inputvalues['forum_title']) ? $inputvalues['forum_title'] : null,ENT_QUOTES,$charset));
  314. $defaults['forum_comment']=prepare4display(isset($inputvalues['forum_comment'])?$inputvalues['forum_comment']:null);
  315. $defaults['forum_category']=isset($inputvalues['forum_category']) ? $inputvalues['forum_category'] : null;
  316. $defaults['allow_anonymous_group']['allow_anonymous']=isset($inputvalues['allow_anonymous']) ? $inputvalues['allow_anonymous'] :null;
  317. $defaults['students_can_edit_group']['students_can_edit']=isset($inputvalues['allow_edit'])?$inputvalues['allow_edit']:null;
  318. $defaults['approval_direct_group']['approval_direct']=isset($inputvalues['approval_direct_post'])?$inputvalues['approval_direct_post']:null;
  319. $defaults['allow_attachments_group']['allow_attachments']=isset($inputvalues['allow_attachments'])?$inputvalues['allow_attachments']:null;
  320. $defaults['allow_new_threads_group']['allow_new_threads']=isset($inputvalues['allow_new_threads'])?$inputvalues['allow_new_threads']:null;
  321. $defaults['default_view_type_group']['default_view_type']=isset($inputvalues['default_view'])?$inputvalues['default_view']:null;
  322. $defaults['public_private_group_forum_group']['public_private_group_forum']=isset($inputvalues['forum_group_public_private'])?$inputvalues['forum_group_public_private']:null;
  323. $defaults['group_forum']=isset($inputvalues['forum_of_group'])?$inputvalues['forum_of_group']:null;
  324. }
  325. $form->setDefaults($defaults);
  326. // The validation or display
  327. if( $form->validate() ) {
  328. $check = Security::check_token('post');
  329. if ($check) {
  330. $values = $form->exportValues();
  331. store_forum($values);
  332. }
  333. Security::clear_token();
  334. } else {
  335. $token = Security::get_token();
  336. $form->addElement('hidden','sec_token');
  337. $form->setConstants(array('sec_token' => $token));
  338. $form->display();
  339. }
  340. }
  341. /**
  342. * This function deletes the forum image if exists
  343. *
  344. * @param int forum id
  345. * @return boolean true if success
  346. * @author Julio Montoya <gugli100@gmail.com>, Dokeos
  347. * @version february 2006, dokeos 1.8
  348. */
  349. function delete_forum_image($forum_id)
  350. {
  351. $table_forums = Database::get_course_table(TABLE_FORUM);
  352. echo '<br />';
  353. $sql="SELECT forum_image FROM $table_forums WHERE forum_id = '".$forum_id."' ";
  354. $result=api_sql_query($sql,__FILE__,__LINE__);
  355. $row=Database::fetch_array($result);
  356. if ($row['forum_image']!='') {
  357. $del_file = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/upload/forum/images/'.$row['forum_image'];
  358. return @unlink($del_file);
  359. } else {
  360. return false;
  361. }
  362. }
  363. /**
  364. * This function displays the form that is used to edit a forum category.
  365. * This is more or less a copy from the show_add_forumcategory_form function with the only difference that is uses
  366. * some default values. I tried to have both in one function but this gave problems with the handle_forum_and_forumcategories function
  367. * (storing was done twice)
  368. *
  369. * @param
  370. * @return
  371. *
  372. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  373. * @version february 2006, dokeos 1.8
  374. */
  375. function show_edit_forumcategory_form($inputvalues=array()) {
  376. // initiate the object
  377. $form = new FormValidator('forumcategory','post');
  378. // settting the form elements
  379. $form->addElement('header', '', get_lang('EditForumCategory'));
  380. $form->addElement('hidden', 'forum_category_id');
  381. $form->addElement('text', 'forum_category_title', get_lang('Title'),'class="input_titles"');
  382. $form->addElement('html_editor', 'forum_category_comment', get_lang('Comment'));
  383. $form->addElement('submit', 'SubmitEditForumCategory',get_lang('Ok'));
  384. global $charset;
  385. // setting the default values
  386. $defaultvalues['forum_category_id']=$inputvalues['cat_id'];
  387. $defaultvalues['forum_category_title']=prepare4display(html_entity_decode($inputvalues['cat_title'],ENT_QUOTES,$charset));
  388. $defaultvalues['forum_category_comment']=prepare4display($inputvalues['cat_comment']);
  389. $form->setDefaults($defaultvalues);
  390. // setting the rules
  391. $form->addRule('forum_category_title', get_lang('ThisFieldIsRequired'), 'required');
  392. // The validation or display
  393. if ( $form->validate() ) {
  394. $check = Security::check_token('post');
  395. if ($check) {
  396. $values = $form->exportValues();
  397. store_forumcategory($values);
  398. }
  399. Security::clear_token();
  400. } else {
  401. $token = Security::get_token();
  402. $form->addElement('hidden','sec_token');
  403. $form->setConstants(array('sec_token' => $token));
  404. $form->display();
  405. }
  406. }
  407. /**
  408. * This function stores the forum category in the database. The new category is added to the end.
  409. *
  410. * @param
  411. * @return
  412. *
  413. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  414. * @version february 2006, dokeos 1.8
  415. */
  416. function store_forumcategory($values) {
  417. global $table_categories;
  418. global $_course;
  419. global $_user;
  420. // find the max cat_order. The new forum category is added at the end => max cat_order + &
  421. $sql="SELECT MAX(cat_order) as sort_max FROM ".Database::escape_string($table_categories);
  422. $result=api_sql_query($sql,__FILE__,__LINE__);
  423. $row=Database::fetch_array($result);
  424. $new_max=$row['sort_max']+1;
  425. $clean_cat_title=Security::remove_XSS(Database::escape_string($values['forum_category_title']));
  426. if (isset($values['forum_category_id'])) { // storing an edit
  427. $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'])."'";
  428. api_sql_query($sql,__FILE__,__LINE__);
  429. $last_id=Database::get_last_insert_id();
  430. api_item_property_update($_course, TOOL_FORUM_CATEGORY, $values['forum_category_id'],"ForumCategoryAdded", api_get_user_id());
  431. $return_message=get_lang('ForumCategoryEdited');
  432. } else {
  433. $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)."')";
  434. api_sql_query($sql,__FILE__,__LINE__);
  435. $last_id=Database::get_last_insert_id();
  436. api_item_property_update($_course, TOOL_FORUM_CATEGORY, $last_id,"ForumCategoryAdded", api_get_user_id());
  437. $return_message=get_lang('ForumCategoryAdded');
  438. }
  439. Display :: display_confirmation_message($return_message);
  440. }
  441. /**
  442. * This function stores the forum in the database. The new forum is added to the end.
  443. *
  444. * @param
  445. * @return
  446. *
  447. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  448. * @version february 2006, dokeos 1.8
  449. */
  450. function store_forum($values) {
  451. global $_course;
  452. global $_user;
  453. $table_forums = Database::get_course_table(TABLE_FORUM);
  454. // find the max forum_order for the given category. The new forum is added at the end => max cat_order + &
  455. $sql="SELECT MAX(forum_order) as sort_max FROM ".$table_forums." WHERE forum_category=".Database::escape_string($values['forum_category']);
  456. $result=api_sql_query($sql,__FILE__,__LINE__);
  457. $row=Database::fetch_array($result);
  458. $new_max=$row['sort_max']+1;
  459. $session_id = isset($_SESSION['id_session']) ? $_SESSION['id_session'] : 0;
  460. $clean_title=Security::remove_XSS(Database::escape_string(htmlspecialchars($values['forum_title'])));
  461. // forum images
  462. $image_moved=false;
  463. if (!empty($_FILES['picture']['name'])) {
  464. $upload_ok = process_uploaded_file($_FILES['picture']);
  465. $has_attachment=true;
  466. } else {
  467. $image_moved=true;
  468. }
  469. // remove existing picture if asked
  470. if (!empty($_POST['remove_picture'])) {
  471. delete_forum_image($values['forum_id']);
  472. }
  473. if (isset($upload_ok)) {
  474. if ($has_attachment) {
  475. $courseDir = $_course['path'].'/upload/forum/images';
  476. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  477. $updir = $sys_course_path.$courseDir;
  478. // Try to add an extension to the file if it hasn't one
  479. $new_file_name = add_ext_on_mime(Database::escape_string($_FILES['picture']['name']), $_FILES['picture']['type']);
  480. // user's file name
  481. $file_name =$_FILES['picture']['name'];
  482. if (!filter_extension($new_file_name)) {
  483. //Display :: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
  484. $image_moved=false;
  485. } else {
  486. $file_extension = explode('.', $_FILES['picture']['name']);
  487. $file_extension = strtolower($file_extension[sizeof($file_extension) - 1]);
  488. $new_file_name = uniqid('').'.'.$file_extension;
  489. $new_path=$updir.'/'.$new_file_name;
  490. $result= @move_uploaded_file($_FILES['picture']['tmp_name'], $new_path);
  491. // Storing the attachments if any
  492. if ($result) {
  493. $image_moved=true;
  494. }
  495. }
  496. }
  497. }
  498. if (isset($values['forum_id'])) {
  499. $sql_image=isset($sql_image)?$sql_image:'';
  500. $new_file_name=isset($new_file_name) ? $new_file_name:'';
  501. if ($image_moved) {
  502. if(empty($_FILES['picture']['name'])){
  503. $sql_image=" ";
  504. } else {
  505. $sql_image=" forum_image='".Database::escape_string($new_file_name)."', ";
  506. delete_forum_image($values['forum_id']);
  507. }
  508. }
  509. // storing an edit
  510. $sql="UPDATE ".$table_forums." SET
  511. forum_title='".$clean_title."',
  512. ".$sql_image."
  513. forum_comment='".Database::escape_string($values['forum_comment'])."',
  514. forum_category='".Database::escape_string($values['forum_category'])."',
  515. allow_anonymous='".Database::escape_string(isset($values['allow_anonymous_group']['allow_anonymous'])?$values['allow_anonymous_group']['allow_anonymous']:null)."',
  516. allow_edit='".Database::escape_string($values['students_can_edit_group']['students_can_edit'])."',
  517. approval_direct_post='".Database::escape_string(isset($values['approval_direct_group']['approval_direct'])?$values['approval_direct_group']['approval_direct']:null)."',
  518. allow_attachments='".Database::escape_string(isset($values['allow_attachments_group']['allow_attachments'])?$values['allow_attachments_group']['allow_attachments']:null)."',
  519. allow_new_threads='".Database::escape_string($values['allow_new_threads_group']['allow_new_threads'])."',
  520. forum_group_public_private='".Database::escape_string($values['public_private_group_forum_group']['public_private_group_forum'])."',
  521. default_view='".Database::escape_string($values['default_view_type_group']['default_view_type'])."',
  522. forum_of_group='".Database::escape_string($values['group_forum'])."'
  523. WHERE forum_id='".Database::escape_string($values['forum_id'])."'";
  524. api_sql_query($sql,__FILE__,__LINE__);
  525. $return_message=get_lang('ForumEdited');
  526. } else {
  527. $sql_image='';
  528. if ($image_moved) {
  529. $new_file_name=isset($new_file_name)?$new_file_name:'';
  530. $sql_image="'".$new_file_name."', ";
  531. }
  532. $sql="INSERT INTO ".$table_forums."
  533. (forum_title, forum_image, 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)
  534. VALUES ('".$clean_title."',
  535. ".$sql_image."
  536. '".Database::escape_string(isset($values['forum_comment'])?$values['forum_comment']:null)."',
  537. '".Database::escape_string(isset($values['forum_category'])?$values['forum_category']:null)."',
  538. '".Database::escape_string(isset($values['allow_anonymous_group']['allow_anonymous'])?$values['allow_anonymous_group']['allow_anonymous']:null)."',
  539. '".Database::escape_string(isset($values['students_can_edit_group']['students_can_edit'])?$values['students_can_edit_group']['students_can_edit']:null)."',
  540. '".Database::escape_string(isset($values['approval_direct_group']['approval_direct'])?$values['approval_direct_group']['approval_direct']:null)."',
  541. '".Database::escape_string(isset($values['allow_attachments_group']['allow_attachments'])?$values['allow_attachments_group']['allow_attachments']:null)."',
  542. '".Database::escape_string(isset($values['allow_new_threads_group']['allow_new_threads'])?$values['allow_new_threads_group']['allow_new_threads']:null)."',
  543. '".Database::escape_string(isset($values['default_view_type_group']['default_view_type'])?$values['default_view_type_group']['default_view_type']:null)."',
  544. '".Database::escape_string(isset($values['group_forum'])?$values['group_forum']:null)."',
  545. '".Database::escape_string(isset($values['public_private_group_forum_group']['public_private_group_forum'])?$values['public_private_group_forum_group']['public_private_group_forum']:null)."',
  546. '".Database::escape_string(isset($new_max)?$new_max:null)."',
  547. ".intval($session_id).")";
  548. api_sql_query($sql,__FILE__,__LINE__);
  549. $last_id=Database::get_last_insert_id();
  550. api_item_property_update($_course, TOOL_FORUM, $last_id,"ForumCategoryAdded", api_get_user_id());
  551. $return_message=get_lang('ForumAdded');
  552. }
  553. return $return_message;
  554. }
  555. /**
  556. * This function deletes a forum or a forum category
  557. * This function currently does not delete the forums inside the category, nor the threads and replies inside these forums.
  558. * For the moment this is the easiest method and it has the advantage that it allows to recover fora that were acidently deleted
  559. * when the forum category got deleted.
  560. *
  561. * @param $content = what we are deleting (a forum or a forum category)
  562. * @param $id The id of the forum category that has to be deleted.
  563. *
  564. * @todo write the code for the cascading deletion of the forums inside a forum category and also the threads and replies inside these forums
  565. * @todo config setting for recovery or not (see also the documents tool: real delete or not).
  566. *
  567. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  568. * @version february 2006, dokeos 1.8
  569. */
  570. function delete_forum_forumcategory_thread($content, $id) {
  571. global $_course;
  572. $table_forums = Database::get_course_table(TABLE_FORUM);
  573. $table_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
  574. if ($content=='forumcategory') {
  575. $tool_constant=TOOL_FORUM_CATEGORY;
  576. $return_message=get_lang('ForumCategoryDeleted');
  577. if (!empty($forum_list)){
  578. $sql="SELECT forum_id FROM ". $table_forums . "WHERE forum_category='".$id."'";
  579. $result = api_sql_query($sql, __FILE__, __LINE__);
  580. $row = Database::fetch_array($result);
  581. foreach ($row as $arr_forum) {
  582. $forum_id = $arr_forum['forum_id'];
  583. api_item_property_update($_course,'forum',$forum_id,'delete',api_get_user_id());
  584. }
  585. }
  586. }
  587. if ($content=='forum') {
  588. $tool_constant=TOOL_FORUM;
  589. $return_message=get_lang('ForumDeleted');
  590. if (!empty($number_threads)){
  591. $sql="SELECT thread_id FROM". $table_forum_thread . "WHERE forum_id='".$id."'";
  592. $result = api_sql_query($sql, __FILE__, __LINE__);
  593. $row = mysql_fetch_array($result);
  594. foreach ($row as $arr_forum) {
  595. $forum_id = $arr_forum['thread_id'];
  596. api_item_property_update($_course,'forum_thread',$forum_id,'delete',api_get_user_id());
  597. }
  598. }
  599. }
  600. if ($content=='thread') {
  601. $tool_constant=TOOL_FORUM_THREAD;
  602. $return_message=get_lang('ThreadDeleted');
  603. }
  604. 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;
  605. //delete_attachment($post_id);
  606. return $return_message;
  607. }
  608. /**
  609. * This function deletes a forum post. This separate function is needed because forum posts do not appear in the item_property table (yet)
  610. * and because deleting a post also has consequence on the posts that have this post as parent_id (they are also deleted).
  611. * an alternative would be to store the posts also in item_property and mark this post as deleted (visibility = 2).
  612. * We also have to decrease the number of replies in the thread table
  613. *
  614. * @param $post_id the id of the post that will be deleted
  615. *
  616. * @todo write recursive function that deletes all the posts that have this message as parent
  617. *
  618. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  619. * @version february 2006, dokeos 1.8
  620. */
  621. function delete_post($post_id) {
  622. global $table_posts;
  623. global $table_threads;
  624. $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.
  625. api_sql_query($sql,__FILE__,__LINE__);
  626. delete_attachment($post_id);
  627. $last_post_of_thread=check_if_last_post_of_thread(strval(intval($_GET['thread'])));
  628. if (is_array($last_post_of_thread)) {
  629. // Decreasing the number of replies for this thread and also changing the last post information
  630. $sql="UPDATE $table_threads SET thread_replies=thread_replies-1,
  631. thread_last_post='".Database::escape_string($last_post_of_thread['post_id'])."',
  632. thread_date='".Database::escape_string($last_post_of_thread['post_date'])."'
  633. WHERE thread_id='".Database::escape_string($_GET['thread'])."'";
  634. api_sql_query($sql,__FILE__,__LINE__);
  635. return 'PostDeleted';
  636. }
  637. if ($last_post_of_thread==false) {
  638. // we deleted the very single post of the thread so we need to delete the entry in the thread table also.
  639. $sql="DELETE FROM $table_threads WHERE thread_id='".Database::escape_string($_GET['thread'])."'";
  640. api_sql_query($sql,__FILE__,__LINE__);
  641. return 'PostDeletedSpecial';
  642. }
  643. }
  644. /**
  645. * This function gets the all information of the last (=most recent) post of the thread
  646. * This can be done by sorting the posts that have the field thread_id=$thread_id and sort them by post_date
  647. *
  648. * @param $thread_id the id of the thread we want to know the last post of.
  649. * @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
  650. *
  651. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  652. * @version february 2006, dokeos 1.8
  653. */
  654. function check_if_last_post_of_thread($thread_id) {
  655. global $table_posts;
  656. $sql="SELECT * FROM $table_posts WHERE thread_id='".Database::escape_string($thread_id)."' ORDER BY post_date DESC";
  657. $result=api_sql_query($sql,__FILE__,__LINE__);
  658. if ( Database::num_rows($result)>0 ) {
  659. $row=Database::fetch_array($result);
  660. return $row;
  661. } else {
  662. return false;
  663. }
  664. }
  665. /**
  666. * This function takes care of the display of the visibility icon
  667. *
  668. * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  669. * @param $id the id of the content we want to make invisible
  670. * @param $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
  671. * @return
  672. *
  673. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  674. * @version february 2006, dokeos 1.8
  675. */
  676. function display_visible_invisible_icon($content, $id, $current_visibility_status, $additional_url_parameters='') {
  677. global $origin;
  678. $id = Security::remove_XSS($id);
  679. if ($current_visibility_status=='1') {
  680. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
  681. if (is_array($additional_url_parameters)) {
  682. foreach ($additional_url_parameters as $key=>$value) {
  683. echo $key.'='.$value.'&amp;';
  684. }
  685. }
  686. echo 'action=invisible&amp;content='.$content.'&amp;id='.$id.'&amp;origin='.$origin.'">'.icon('../img/visible.gif',get_lang('MakeInvisible')).'</a>';
  687. }
  688. if ($current_visibility_status=='0') {
  689. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
  690. if (is_array($additional_url_parameters)) {
  691. foreach ($additional_url_parameters as $key=>$value) {
  692. echo $key.'='.$value.'&amp;';
  693. }
  694. }
  695. echo 'action=visible&amp;content='.$content.'&amp;id='.$id.'&amp;origin='.$origin.'">'.icon('../img/invisible.gif',get_lang('MakeVisible')).'</a>';
  696. }
  697. }
  698. /**
  699. * This function takes care of the display of the lock icon
  700. *
  701. * @param $content what is it that we want to (un)lock: forum category, forum, thread, post
  702. * @param $id the id of the content we want to (un)lock
  703. * @param $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
  704. * @return
  705. *
  706. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  707. * @version february 2006, dokeos 1.8
  708. */
  709. function display_lock_unlock_icon($content, $id, $current_lock_status, $additional_url_parameters='')
  710. {
  711. $id = Security::remove_XSS($id);
  712. if ($current_lock_status=='1')
  713. {
  714. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
  715. if (is_array($additional_url_parameters))
  716. {
  717. foreach ($additional_url_parameters as $key=>$value)
  718. {
  719. echo $key.'='.$value.'&amp;';
  720. }
  721. }
  722. echo 'action=unlock&amp;content='.$content.'&amp;id='.$id.'">'.icon('../img/lock.gif',get_lang('Unlock')).'</a>';
  723. }
  724. if ($current_lock_status=='0')
  725. {
  726. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&';
  727. if (is_array($additional_url_parameters))
  728. {
  729. foreach ($additional_url_parameters as $key=>$value)
  730. {
  731. echo $key.'='.$value.'&amp;';
  732. }
  733. }
  734. echo 'action=lock&amp;content='.$content.'&amp;id='.$id.'">'.icon('../img/unlock.gif',get_lang('Lock')).'</a>';
  735. }
  736. }
  737. /**
  738. * This function takes care of the display of the up and down icon
  739. *
  740. * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  741. * @param $id is the id of the item we want to display the icons for
  742. * @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)
  743. * The key of this $list array is the id of the item.
  744. *
  745. * @return
  746. *
  747. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  748. * @version february 2006, dokeos 1.8
  749. */
  750. function display_up_down_icon($content, $id, $list) {
  751. $id = strval(intval($id));
  752. $total_items=count($list);
  753. $position = 0;
  754. $internal_counter=0;
  755. if(is_array($list)) {
  756. foreach ($list as $key=>$listitem) {
  757. $internal_counter++;
  758. if ($id==$key) {
  759. $position=$internal_counter;
  760. }
  761. }
  762. }
  763. if ($position>1) {
  764. $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>';
  765. } else {
  766. $return_value='<img src="../img/up_na.gif" />';
  767. }
  768. if ($position<$total_items) {
  769. $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>';
  770. } else {
  771. $return_value.='<img src="../img/down_na.gif" />';
  772. }
  773. echo $return_value;
  774. }
  775. /**
  776. * This function changes the visibility in the database (item_property)
  777. *
  778. * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  779. * @param $id the id of the content we want to make invisible
  780. * @param $target_visibility what is the current status of the visibility (0 = invisible, 1 = visible)
  781. *
  782. * @todo change the get parameter so that it matches the tool constants.
  783. * @todo check if api_item_property_update returns true or false => returnmessage depends on it.
  784. * @todo move to itemmanager
  785. *
  786. * @return
  787. *
  788. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  789. * @version february 2006, dokeos 1.8
  790. */
  791. function change_visibility($content, $id, $target_visibility) {
  792. global $_course;
  793. $constants=array('forumcategory'=>TOOL_FORUM_CATEGORY, 'forum'=>TOOL_FORUM, 'thread'=>TOOL_FORUM_THREAD);
  794. 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.
  795. if ($target_visibility=='visible') {
  796. handle_mail_cue($content, $id);
  797. }
  798. return get_lang('VisibilityChanged');
  799. }
  800. /**
  801. * This function changes the lock status in the database
  802. *
  803. * @param $content what is it that we want to (un)lock: forum category, forum, thread, post
  804. * @param $id the id of the content we want to (un)lock
  805. * @param $action do we lock (=>locked value in db = 1) or unlock (=> locked value in db = 0)
  806. * @return string, language variable
  807. *
  808. * @todo move to itemmanager
  809. *
  810. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  811. * @version february 2006, dokeos 1.8
  812. */
  813. function change_lock_status($content, $id, $action) {
  814. global $table_categories;
  815. global $table_forums;
  816. global $table_threads;
  817. global $table_posts;
  818. // Determine the relevant table
  819. if ($content=='forumcategory') {
  820. $table=$table_categories;
  821. $id_field='cat_id';
  822. } elseif ($content=='forum') {
  823. $table=$table_forums;
  824. $id_field='forum_id';
  825. } elseif ($content=='thread') {
  826. $table=$table_threads;
  827. $id_field='thread_id';
  828. } else {
  829. return get_lang('Error');
  830. }
  831. // Determine what we are doing => defines the value for the database and the return message
  832. if ($action=='lock') {
  833. $db_locked=1;
  834. $return_message=get_lang('Locked');
  835. } elseif ($action=='unlock') {
  836. $db_locked=0;
  837. $return_message=get_lang('Unlocked');
  838. } else {
  839. return get_lang('Error');
  840. }
  841. // Doing the change in the database
  842. $sql="UPDATE $table SET locked='".Database::escape_string($db_locked)."' WHERE $id_field='".Database::escape_string($id)."'";
  843. if (api_sql_query($sql,__FILE__,__LINE__)) {
  844. return $return_message;
  845. } else {
  846. return get_lang('Error');
  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. global $table_categories;
  864. global $table_forums;
  865. global $table_item_property;
  866. // Determine which field holds the sort order
  867. if ($content=='forumcategory') {
  868. $table=$table_categories;
  869. $sort_column='cat_order';
  870. $id_column='cat_id';
  871. $sort_column='cat_order';
  872. } elseif ($content=='forum') {
  873. $table=$table_forums;
  874. $sort_column='forum_order';
  875. $id_column='forum_id';
  876. $sort_column='forum_order';
  877. // we also need the forum_category of this forum
  878. $sql="SELECT forum_category FROM $table_forums WHERE forum_id=".Database::escape_string($id);
  879. $result=api_sql_query($sql,__FILE__,__LINE__);
  880. $row=Database::fetch_array($result);
  881. $forum_category=$row['forum_category'];
  882. } else {
  883. return get_lang('Error');
  884. }
  885. // determine if need to sort ascending or descending
  886. if ($direction=='down') {
  887. $sort_direction='ASC';
  888. } elseif ($direction=='up') {
  889. $sort_direction='DESC';
  890. } else {
  891. return get_lang('Error');
  892. }
  893. // The SQL statement
  894. if ($content=='forumcategory') {
  895. $sql="SELECT * FROM".$table_categories." forum_categories, ".$table_item_property." item_properties
  896. WHERE forum_categories.cat_id=item_properties.ref
  897. AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  898. ORDER BY forum_categories.cat_order $sort_direction";
  899. }
  900. if ($content=='forum') {
  901. $sql="SELECT * FROM".$table." WHERE forum_category='".Database::escape_string($forum_category)."' ORDER BY forum_order $sort_direction";
  902. }
  903. // echo $sql.'<br />';
  904. // finding the items that need to be switched
  905. $result=api_sql_query($sql,__FILE__,__LINE__);
  906. $found=false;
  907. while ($row=Database::fetch_array($result)) {
  908. //echo $row[$id_column].'-';
  909. if ($found==true) {
  910. $next_id=$row[$id_column];
  911. $next_sort=$row[$sort_column];
  912. $found=false;
  913. }
  914. if($id==$row[$id_column]) {
  915. $this_id=$id;
  916. $this_sort=$row[$sort_column];
  917. $found=true;
  918. }
  919. }
  920. // Committing the switch
  921. // we do an extra check if we do not have illegal values. If your remove this if statment you will
  922. // be able to mess with the sorting by refreshing the page over and over again.
  923. if ($this_sort<>'' && $next_sort<>'' && $next_id<>'' && $this_id<>'') {
  924. $sql_update1="UPDATE $table SET $sort_column='".Database::escape_string($this_sort)."' WHERE $id_column='".Database::escape_string($next_id)."'";
  925. $sql_update2="UPDATE $table SET $sort_column='".Database::escape_string($next_sort)."' WHERE $id_column='".Database::escape_string($this_id)."'";
  926. api_sql_query($sql_update1,__FILE__,__LINE__);
  927. api_sql_query($sql_update2,__FILE__,__LINE__);
  928. }
  929. return get_lang(ucfirst($content).'Moved');
  930. }
  931. /**
  932. * This function returns a piece of html code that make the links grey (=invisible for the student)
  933. *
  934. * @param boolean 0/1: 0 = invisible, 1 = visible
  935. * @return string
  936. *
  937. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  938. * @version february 2006, dokeos 1.8
  939. */
  940. function class_visible_invisible($current_visibility_status) {
  941. if ($current_visibility_status=='0') {
  942. return "class='invisible'";
  943. }
  944. }
  945. /**
  946. * Retrieve all the information off the forum categories (or one specific) for the current course.
  947. * The categories are sorted according to their sorting order (cat_order
  948. *
  949. * @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.
  950. * @return an array containing all the information about all the forum categories
  951. *
  952. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  953. * @version february 2006, dokeos 1.8
  954. */
  955. function get_forum_categories($id='') {
  956. $table_categories = Database :: get_course_table(TABLE_FORUM_CATEGORY);
  957. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  958. $forum_categories_list=array();
  959. if ($id=='') {
  960. $sql="SELECT * FROM".$table_categories." forum_categories, ".$table_item_property." item_properties
  961. WHERE forum_categories.cat_id=item_properties.ref
  962. AND item_properties.visibility=1
  963. AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  964. ORDER BY forum_categories.cat_order ASC";
  965. if (is_allowed_to_edit()) {
  966. $sql="SELECT * FROM".$table_categories." forum_categories, ".$table_item_property." item_properties
  967. WHERE forum_categories.cat_id=item_properties.ref
  968. AND item_properties.visibility<>2
  969. AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  970. ORDER BY forum_categories.cat_order ASC";
  971. }
  972. } else {
  973. $sql="SELECT * FROM".$table_categories." forum_categories, ".$table_item_property." item_properties
  974. WHERE forum_categories.cat_id=item_properties.ref
  975. AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  976. AND forum_categories.cat_id='".Database::escape_string($id)."'
  977. ORDER BY forum_categories.cat_order ASC";
  978. }
  979. $result=api_sql_query($sql,__FILE__,__LINE__);
  980. while ($row=Database::fetch_array($result)) {
  981. if ($id=='') {
  982. $forum_categories_list[$row['cat_id']]=$row;
  983. } else {
  984. $forum_categories_list=$row;
  985. }
  986. }
  987. return $forum_categories_list;
  988. }
  989. /**
  990. * This function retrieves all the fora in a given forum category
  991. *
  992. * @param integer $cat_id the id of the forum category
  993. * @return an array containing all the information about the forums (regardless of their category)
  994. *
  995. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  996. * @version february 2006, dokeos 1.8
  997. */
  998. function get_forums_in_category($cat_id)
  999. {
  1000. global $table_forums;
  1001. global $table_item_property;
  1002. $forum_list=array();
  1003. $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1004. WHERE forum.forum_category='".Database::escape_string($cat_id)."'
  1005. AND forum.forum_id=item_properties.ref
  1006. AND item_properties.visibility=1
  1007. AND item_properties.tool='".TOOL_FORUM."'
  1008. ORDER BY forum.forum_order ASC";
  1009. if (is_allowed_to_edit()) {
  1010. $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1011. WHERE forum.forum_category='".Database::escape_string($cat_id)."'
  1012. AND forum.forum_id=item_properties.ref
  1013. AND item_properties.visibility<>2
  1014. AND item_properties.tool='".TOOL_FORUM."'
  1015. ORDER BY forum_order ASC";
  1016. }
  1017. $result=api_sql_query($sql,__FILE__,__LINE__);
  1018. while ($row=Database::fetch_array($result)) {
  1019. $forum_list[$row['forum_id']]=$row;
  1020. }
  1021. return $forum_list;
  1022. }
  1023. /**
  1024. * Retrieve all the forums (regardless of their category) or of only one. The forums are sorted according to the forum_order.
  1025. * Since it does not take the forum category into account there probably will be two or more forums that have forum_order=1, ...
  1026. *
  1027. * @return an array containing all the information about the forums (regardless of their category)
  1028. * @todo check $sql4 because this one really looks fishy.
  1029. *
  1030. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1031. * @version february 2006, dokeos 1.8
  1032. */
  1033. function get_forums($id='') {
  1034. global $table_forums;
  1035. global $table_threads;
  1036. global $table_posts;
  1037. global $table_item_property;
  1038. global $table_users;
  1039. // **************** GETTING ALL THE FORUMS ************************* //
  1040. $session_condition = isset($_SESSION['id_session']) ? 'AND forum.session_id IN (0,'.intval($_SESSION['id_session']).')' : '';
  1041. $forum_list = array();
  1042. if ($id=='') {
  1043. //-------------- Student -----------------//
  1044. // select all the forum information of all forums (that are visible to students)
  1045. $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1046. WHERE forum.forum_id=item_properties.ref
  1047. AND item_properties.visibility=1
  1048. AND item_properties.tool='".TOOL_FORUM."'
  1049. $session_condition
  1050. ORDER BY forum.forum_order ASC";
  1051. // select the number of threads of the forums (only the threads that are visible)
  1052. $sql2="SELECT count(*) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  1053. WHERE threads.thread_id=item_properties.ref
  1054. AND item_properties.visibility=1
  1055. AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1056. GROUP BY threads.forum_id";
  1057. // select the number of posts of the forum (post that are visible and that are in a thread that is visible)
  1058. $sql3="SELECT count(*) AS number_of_posts, posts.forum_id FROM $table_posts posts, $table_threads threads, ".$table_item_property." item_properties
  1059. WHERE posts.visible=1
  1060. AND posts.thread_id=threads.thread_id
  1061. AND threads.thread_id=item_properties.ref
  1062. AND item_properties.visibility=1
  1063. AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1064. GROUP BY threads.forum_id";
  1065. //-------------- Course Admin -----------------//
  1066. if (is_allowed_to_edit()) {
  1067. // select all the forum information of all forums (that are not deleted)
  1068. $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1069. WHERE forum.forum_id=item_properties.ref
  1070. AND item_properties.visibility<>2
  1071. AND item_properties.tool='".TOOL_FORUM."'
  1072. $session_condition
  1073. ORDER BY forum_order ASC";
  1074. //echo $sql.'<hr>';
  1075. // select the number of threads of the forums (only the threads that are not deleted)
  1076. $sql2="SELECT count(*) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  1077. WHERE threads.thread_id=item_properties.ref
  1078. AND item_properties.visibility<>2
  1079. AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1080. GROUP BY threads.forum_id";
  1081. //echo $sql2.'<hr>';
  1082. // select the number of posts of the forum
  1083. $sql3="SELECT count(*) AS number_of_posts, forum_id FROM $table_posts GROUP BY forum_id";
  1084. //echo $sql3.'<hr>';
  1085. }
  1086. }
  1087. // **************** GETTING ONE SPECIFIC FORUM ************************* //
  1088. // 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
  1089. // 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
  1090. // when editing a forum (and for the moment it is the only place where we use this part of the function)
  1091. else {
  1092. // select all the forum information of the given forum (that is not deleted)
  1093. $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1094. WHERE forum.forum_id=item_properties.ref
  1095. AND forum_id='".Database::escape_string($id)."'
  1096. AND item_properties.visibility<>2
  1097. AND item_properties.tool='".TOOL_FORUM."'
  1098. $session_condition
  1099. ORDER BY forum_order ASC";
  1100. // select the number of threads of the forum
  1101. $sql2="SELECT count(*) AS number_of_threads, forum_id FROM $table_threads WHERE forum_id=".Database::escape_string($id)." GROUP BY forum_id";
  1102. // select the number of posts of the forum
  1103. $sql3="SELECT count(*) AS number_of_posts, forum_id FROM $table_posts WHERE forum_id=".Database::escape_string($id)." GROUP BY forum_id";
  1104. // select the last post and the poster (note: this is probably no longer needed)
  1105. $sql4="SELECT post.post_id, post.forum_id, post.poster_id, post.poster_name, post.post_date, users.lastname, users.firstname
  1106. FROM $table_posts post, $table_users users
  1107. WHERE forum_id=".Database::escape_string($id)."
  1108. AND post.poster_id=users.user_id
  1109. GROUP BY post.forum_id
  1110. ORDER BY post.post_id ASC";
  1111. }
  1112. // handling all the forum information
  1113. $result=api_sql_query($sql,__FILE__,__LINE__);
  1114. while ($row=Database::fetch_array($result)) {
  1115. if ($id=='') {
  1116. $forum_list[$row['forum_id']]=$row;
  1117. } else {
  1118. $forum_list=$row;
  1119. }
  1120. }
  1121. // handling the threadcount information
  1122. $result2=api_sql_query($sql2,__FILE__,__LINE__);
  1123. while ($row2=Database::fetch_array($result2)) {
  1124. if ($id=='') {
  1125. $forum_list[$row2['forum_id']]['number_of_threads']=$row2['number_of_threads'];
  1126. } else {
  1127. $forum_list['number_of_threads']=$row2['number_of_threads'];;
  1128. }
  1129. }
  1130. // handling the postcount information
  1131. $result3=api_sql_query($sql3,__FILE__,__LINE__);
  1132. while ($row3=Database::fetch_array($result3)) {
  1133. if ($id=='') {
  1134. if (array_key_exists($row3['forum_id'],$forum_list)) {// this is needed because sql3 takes also the deleted forums into account
  1135. $forum_list[$row3['forum_id']]['number_of_posts']=$row3['number_of_posts'];
  1136. }
  1137. } else {
  1138. $forum_list['number_of_posts']=$row3['number_of_posts'];
  1139. }
  1140. }
  1141. // finding the last post information (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)
  1142. if ($id=='') {
  1143. if(is_array($forum_list)) {
  1144. foreach ($forum_list as $key=>$value) {
  1145. $last_post_info_of_forum=get_last_post_information($key,is_allowed_to_edit());
  1146. $forum_list[$key]['last_post_id']=$last_post_info_of_forum['last_post_id'];
  1147. $forum_list[$key]['last_poster_id']=$last_post_info_of_forum['last_poster_id'];
  1148. $forum_list[$key]['last_post_date']=$last_post_info_of_forum['last_post_date'];
  1149. $forum_list[$key]['last_poster_name']=$last_post_info_of_forum['last_poster_name'];
  1150. $forum_list[$key]['last_poster_lastname']=$last_post_info_of_forum['last_poster_lastname'];
  1151. $forum_list[$key]['last_poster_firstname']=$last_post_info_of_forum['last_poster_firstname'];
  1152. }
  1153. } else {
  1154. $forum_list = array();
  1155. }
  1156. } else {
  1157. $last_post_info_of_forum=get_last_post_information($id,is_allowed_to_edit());
  1158. $forum_list['last_post_id']=$last_post_info_of_forum['last_post_id'];
  1159. $forum_list['last_poster_id']=$last_post_info_of_forum['last_poster_id'];
  1160. $forum_list['last_post_date']=$last_post_info_of_forum['last_post_date'];
  1161. $forum_list['last_poster_name']=$last_post_info_of_forum['last_poster_name'];
  1162. $forum_list['last_poster_lastname']=$last_post_info_of_forum['last_poster_lastname'];
  1163. $forum_list['last_poster_firstname']=$last_post_info_of_forum['last_poster_firstname'];
  1164. }
  1165. return $forum_list;
  1166. }
  1167. /**
  1168. * This functions gets all the last post information of a certain forum
  1169. *
  1170. * @param $forum_id the id of the forum we want to know the last post information of.
  1171. * @param $show_invisibles
  1172. * @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)
  1173. *
  1174. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1175. * @version february 2006, dokeos 1.8
  1176. */
  1177. function get_last_post_information($forum_id, $show_invisibles=false) {
  1178. global $table_forums;
  1179. global $table_threads;
  1180. global $table_posts;
  1181. global $table_item_property;
  1182. global $table_users;
  1183. $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
  1184. FROM $table_posts post, $table_users users, $table_item_property thread_properties, $table_item_property forum_properties
  1185. WHERE post.forum_id=".Database::escape_string($forum_id)."
  1186. AND post.poster_id=users.user_id
  1187. AND post.thread_id=thread_properties.ref
  1188. AND thread_properties.tool='".TOOL_FORUM_THREAD."'
  1189. AND post.forum_id=forum_properties.ref
  1190. AND forum_properties.tool='".TOOL_FORUM."'
  1191. ORDER BY post.post_id DESC";
  1192. $result=api_sql_query($sql,__FILE__,__LINE__);
  1193. if ($show_invisibles==true) {
  1194. $row=Database::fetch_array($result);
  1195. $return_array['last_post_id']=$row['post_id'];
  1196. $return_array['last_poster_id']=$row['poster_id'];
  1197. $return_array['last_post_date']=$row['post_date'];
  1198. $return_array['last_poster_name']=$row['poster_name'];
  1199. $return_array['last_poster_lastname']=$row['lastname'];
  1200. $return_array['last_poster_firstname']=$row['firstname'];
  1201. return $return_array;
  1202. } else {
  1203. // 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)
  1204. while ($row=Database::fetch_array($result)) {
  1205. if ($row['visible']=='1' AND $row['thread_visibility']=='1' AND $row['forum_visibility']=='1') {
  1206. $return_array['last_post_id']=$row['post_id'];
  1207. $return_array['last_poster_id']=$row['poster_id'];
  1208. $return_array['last_post_date']=$row['post_date'];
  1209. $return_array['last_poster_name']=$row['poster_name'];
  1210. $return_array['last_poster_lastname']=$row['lastname'];
  1211. $return_array['last_poster_firstname']=$row['firstname'];
  1212. return $return_array;
  1213. }
  1214. }
  1215. }
  1216. }
  1217. /**
  1218. * Retrieve all the threads of a given forum
  1219. *
  1220. * @param
  1221. * @return an array containing all the information about the threads
  1222. *
  1223. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1224. * @version february 2006, dokeos 1.8
  1225. */
  1226. function get_threads($forum_id) {
  1227. global $table_item_property;
  1228. global $table_threads;
  1229. global $table_posts;
  1230. global $table_users;
  1231. $thread_list=array();
  1232. // important note: it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
  1233. // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
  1234. // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
  1235. // This is why it is added to the end of the field selection
  1236. $sql = "SELECT thread.*, item_properties.*, post.*, users.firstname, users.lastname, users.user_id,
  1237. 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
  1238. FROM $table_threads thread
  1239. INNER JOIN $table_item_property item_properties
  1240. ON thread.thread_id=item_properties.ref
  1241. AND item_properties.visibility='1'
  1242. AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1243. LEFT JOIN $table_users users
  1244. ON thread.thread_poster_id=users.user_id
  1245. LEFT JOIN $table_posts post
  1246. ON thread.thread_last_post = post.post_id
  1247. LEFT JOIN $table_users last_poster_users
  1248. ON post.poster_id= last_poster_users.user_id
  1249. WHERE thread.forum_id='".Database::escape_string($forum_id)."'
  1250. ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
  1251. if (is_allowed_to_edit()) {
  1252. // important note: it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
  1253. // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
  1254. // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
  1255. // This is why it is added to the end of the field selection
  1256. $sql = "SELECT thread.*, item_properties.*, post.*, users.firstname, users.lastname, users.user_id,
  1257. 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
  1258. FROM $table_threads thread
  1259. INNER JOIN $table_item_property item_properties
  1260. ON thread.thread_id=item_properties.ref
  1261. AND item_properties.visibility<>2
  1262. AND item_properties.tool='".TOOL_FORUM_THREAD."'
  1263. LEFT JOIN $table_users users
  1264. ON thread.thread_poster_id=users.user_id
  1265. LEFT JOIN $table_posts post
  1266. ON thread.thread_last_post = post.post_id
  1267. LEFT JOIN $table_users last_poster_users
  1268. ON post.poster_id= last_poster_users.user_id
  1269. WHERE thread.forum_id='".Database::escape_string($forum_id)."'
  1270. ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
  1271. }
  1272. $result=api_sql_query($sql, __FILE__, __LINE__);
  1273. while ( $row=Database::fetch_array($result,'ASSOC') ) {
  1274. $thread_list[]=$row;
  1275. }
  1276. return $thread_list;
  1277. }
  1278. /**
  1279. * Retrieve all posts of a given thread
  1280. *
  1281. * @return an array containing all the information about the posts of a given thread
  1282. *
  1283. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1284. * @version february 2006, dokeos 1.8
  1285. */
  1286. function get_posts($thread_id) {
  1287. global $table_posts;
  1288. global $table_users;
  1289. // note: change these SQL so that only the relevant fields of the user table are used
  1290. if (api_is_allowed_to_edit()) {
  1291. $sql = "SELECT * FROM $table_posts posts
  1292. LEFT JOIN $table_users users
  1293. ON posts.poster_id=users.user_id
  1294. WHERE posts.thread_id='".Database::escape_string($thread_id)."'
  1295. ORDER BY posts.post_id ASC";
  1296. } else {
  1297. // students can only se the posts that are approved (posts.visible='1')
  1298. $sql = "SELECT * FROM $table_posts posts
  1299. LEFT JOIN $table_users users
  1300. ON posts.poster_id=users.user_id
  1301. WHERE posts.thread_id='".Database::escape_string($thread_id)."'
  1302. AND posts.visible='1'
  1303. ORDER BY posts.post_id ASC";
  1304. }
  1305. $result=api_sql_query($sql, __FILE__, __LINE__);
  1306. while ($row=Database::fetch_array($result)) {
  1307. $post_list[]=$row;
  1308. }
  1309. return $post_list;
  1310. }
  1311. /**
  1312. * This function return the html syntax for the image
  1313. *
  1314. * @param $image_url The url of the image (absolute or relative)
  1315. * @param $alt The alt text (when the images cannot be displayed). http://www.w3.org/TR/html4/struct/objects.html#adef-alt
  1316. * @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
  1317. *
  1318. * @todo this is the same as the Display::xxx function, so it can be removed => all calls have to be changed also
  1319. *
  1320. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1321. * @version february 2006, dokeos 1.8
  1322. */
  1323. function icon($image_url,$alt='',$title='') {
  1324. if ($title=='') {
  1325. $title=$alt;
  1326. }
  1327. return '<img src="'.$image_url.'" alt="'.$alt.'" title="'.$title.'" />';
  1328. }
  1329. /**************************************************************************
  1330. NEW TOPIC FUNCTIONS
  1331. **************************************************************************/
  1332. /**
  1333. * This function retrieves all the information of a post
  1334. *
  1335. * @param $forum_id integer that indicates the forum
  1336. * @return array returns
  1337. *
  1338. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1339. * @version february 2006, dokeos 1.8
  1340. */
  1341. function get_post_information($post_id) {
  1342. global $table_posts;
  1343. global $table_users;
  1344. $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)."'";
  1345. $result=api_sql_query($sql, __FILE__, __LINE__);
  1346. $row=Database::fetch_array($result);
  1347. return $row;
  1348. }
  1349. /**
  1350. * This function retrieves all the information of a thread
  1351. *
  1352. * @param $forum_id integer that indicates the forum
  1353. * @return array returns
  1354. *
  1355. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1356. * @version february 2006, dokeos 1.8
  1357. */
  1358. function get_thread_information($thread_id) {
  1359. global $table_threads;
  1360. global $table_item_property;
  1361. $sql="SELECT * FROM ".$table_threads." threads, ".$table_item_property." item_properties
  1362. WHERE item_properties.tool='".TOOL_FORUM_THREAD."'
  1363. AND item_properties.ref='".Database::escape_string($thread_id)."'
  1364. AND threads.thread_id='".Database::escape_string($thread_id)."'";
  1365. $result=api_sql_query($sql, __FILE__, __LINE__);
  1366. $row=Database::fetch_array($result);
  1367. return $row;
  1368. }
  1369. /**
  1370. * This function retrieves forum thread users details
  1371. * @param int Thread ID
  1372. * @param string Course DB name (optional)
  1373. * @return array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
  1374. * @author Christian Fasanando <christian.fasanando@dokeos.com>,
  1375. * @version octubre 2008, dokeos 1.8
  1376. */
  1377. function get_thread_users_details($thread_id, $db_name = null) {
  1378. $t_posts = Database :: get_course_table(TABLE_FORUM_POST, (empty($db_name)?null:$db_name));
  1379. $t_users = Database :: get_main_table(TABLE_MAIN_USER);
  1380. $sql = "SELECT DISTINCT user_id, lastname, firstname, thread_id
  1381. FROM $t_posts , $t_users
  1382. WHERE poster_id = user_id
  1383. AND thread_id = '".Database::escape_string($thread_id)."'
  1384. AND status not in('1')";
  1385. $result = api_sql_query($sql, __FILE__, __LINE__);
  1386. return $result;
  1387. }
  1388. /**
  1389. * This function retrieves forum thread users qualify
  1390. * @param int Thread ID
  1391. * @param string Course DB name (optional)
  1392. * @return array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
  1393. * @author Jhon Hinojosa<jhon.hinojosa@dokeos.com>,
  1394. * @version octubre 2008, dokeos 1.8
  1395. */
  1396. function get_thread_users_qualify($thread_id, $db_name = null) {
  1397. $t_posts = Database :: get_course_table(TABLE_FORUM_POST, (empty($db_name)?null:$db_name));
  1398. $t_qualify = Database :: get_course_table(TABLE_FORUM_THREAD_QUALIFY, (empty($db_name)?null:$db_name));
  1399. $t_users = Database :: get_main_table(TABLE_MAIN_USER);
  1400. $sql = "SELECT post.poster_id, user.lastname, user.firstname, post.thread_id,user.user_id,qualify.qualify
  1401. FROM $t_posts post,
  1402. $t_qualify qualify,
  1403. $t_users user
  1404. WHERE
  1405. post.poster_id = user.user_id
  1406. AND post.poster_id = qualify.user_id
  1407. AND qualify.thread_id = '".Database::escape_string($thread_id)."'
  1408. AND user.status not in('1')
  1409. GROUP BY post.poster_id ";
  1410. $result = api_sql_query($sql, __FILE__, __LINE__);
  1411. return $result;
  1412. }
  1413. /**
  1414. * This function retrieves forum thread users not qualify
  1415. * @param int Thread ID
  1416. * @param string Course DB name (optional)
  1417. * @return array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
  1418. * @author Jhon Hinojosa<jhon.hinojosa@dokeos.com>,
  1419. * @version octubre 2008, dokeos 1.8
  1420. */
  1421. function get_thread_users_not_qualify($thread_id, $db_name = null) {
  1422. $t_posts = Database :: get_course_table(TABLE_FORUM_POST, (empty($db_name)?null:$db_name));
  1423. $t_qualify = Database :: get_course_table(TABLE_FORUM_THREAD_QUALIFY, (empty($db_name)?null:$db_name));
  1424. $t_users = Database :: get_main_table(TABLE_MAIN_USER);
  1425. $sql1 = "select user_id FROM $t_qualify WHERE thread_id = '".$thread_id."'";
  1426. $result1 = api_sql_query($sql1,__FILE__,__LINE__);
  1427. $cad='';
  1428. while ($row=Database::fetch_array($result1)) {
  1429. $cad .= $row['user_id'].',';
  1430. }
  1431. if($cad=='') {
  1432. $cad='0';
  1433. } else {
  1434. $cad=substr($cad,0,strlen($cad)-1);
  1435. }
  1436. $sql = "SELECT DISTINCT user.user_id, user.lastname, user.firstname, post.thread_id
  1437. FROM $t_posts post, $t_users user
  1438. WHERE post.poster_id = user.user_id
  1439. AND user.user_id NOT IN (".$cad.")
  1440. AND post.thread_id = '".Database::escape_string($thread_id)."'
  1441. AND user.status not in('1')";
  1442. $result = api_sql_query($sql, __FILE__, __LINE__);
  1443. return $result;
  1444. }
  1445. /**
  1446. * This function retrieves all the information of a given forum_id
  1447. *
  1448. * @param $forum_id integer that indicates the forum
  1449. * @return array returns
  1450. *
  1451. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1452. * @version february 2006, dokeos 1.8
  1453. *
  1454. * @deprecated this functionality is now moved to get_forums($forum_id)
  1455. */
  1456. function get_forum_information($forum_id) {
  1457. global $table_forums;
  1458. global $table_item_property;
  1459. $sql="SELECT * FROM ".$table_forums." forums, ".$table_item_property." item_properties
  1460. WHERE item_properties.tool='".TOOL_FORUM."'
  1461. AND item_properties.ref='".Database::escape_string($forum_id)."'
  1462. AND forums.forum_id='".Database::escape_string($forum_id)."'";
  1463. $result=api_sql_query($sql, __FILE__, __LINE__);
  1464. $row=Database::fetch_array($result);
  1465. $row['approval_direct_post'] = 0; // we can't anymore change this option, so it should always be activated
  1466. return $row;
  1467. }
  1468. /**
  1469. * This function retrieves all the information of a given forumcategory id
  1470. *
  1471. * @param $forum_id integer that indicates the forum
  1472. * @return array returns
  1473. *
  1474. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1475. * @version february 2006, dokeos 1.8
  1476. */
  1477. function get_forumcategory_information($cat_id) {
  1478. global $table_categories;
  1479. global $table_item_property;
  1480. $sql="SELECT * FROM ".$table_categories." forumcategories, ".$table_item_property." item_properties
  1481. WHERE item_properties.tool='".TOOL_FORUM_CATEGORY."'
  1482. AND item_properties.ref='".Database::escape_string($cat_id)."'
  1483. AND forumcategories.cat_id='".Database::escape_string($cat_id)."'";
  1484. $result=api_sql_query($sql, __FILE__, __LINE__);
  1485. $row=Database::fetch_array($result);
  1486. return $row;
  1487. }
  1488. /**
  1489. * This function counts the number of forums inside a given category
  1490. *
  1491. * @param $cat_id the id of the forum category
  1492. * @todo an additional parameter that takes the visibility into account. For instance $countinvisible=0 would return the number
  1493. * of visible forums, $countinvisible=1 would return the number of visible and invisible forums
  1494. * @return int the number of forums inside the given category
  1495. *
  1496. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1497. * @version february 2006, dokeos 1.8
  1498. */
  1499. function count_number_of_forums_in_category($cat_id) {
  1500. global $table_forums;
  1501. $sql="SELECT count(*) AS number_of_forums FROM ".$table_forums." WHERE forum_category='".Database::escape_string($cat_id)."'";
  1502. $result=api_sql_query($sql, __FILE__, __LINE__);
  1503. $row=Database::fetch_array($result);
  1504. return $row['number_of_forums'];
  1505. }
  1506. /**
  1507. * This function stores a new thread. This is done through an entry in the forum_thread table AND
  1508. * in the forum_post table because. The threads are also stored in the item_property table. (forum posts are not (yet))
  1509. *
  1510. * @param
  1511. * @return
  1512. *
  1513. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1514. * @version february 2006, dokeos 1.8
  1515. */
  1516. function store_thread($values) {
  1517. global $table_threads;
  1518. global $table_posts;
  1519. global $_user;
  1520. global $_course;
  1521. global $current_forum;
  1522. global $origin;
  1523. global $forum_table_attachment;
  1524. $upload_ok=1;
  1525. $has_attachment=false;
  1526. if(!empty($_FILES['user_upload']['name'])) {
  1527. $upload_ok = process_uploaded_file($_FILES['user_upload']);
  1528. $has_attachment=true;
  1529. }
  1530. if($upload_ok) {
  1531. $post_date=date('Y-m-d H:i:s');
  1532. if ($current_forum['approval_direct_post']=='1' AND !api_is_allowed_to_edit()) {
  1533. $visible=0; // the post is not approved yet.
  1534. } else {
  1535. $visible=1;
  1536. }
  1537. $clean_post_title=Security::remove_XSS(Database::escape_string(htmlspecialchars($values['post_title'])));
  1538. // We first store an entry in the forum_thread table because the thread_id is used in the forum_post table
  1539. $sql="INSERT INTO $table_threads (thread_title, forum_id, thread_poster_id, thread_poster_name, thread_date, thread_sticky,thread_title_qualify,thread_qualify_max,thread_weight,session_id)
  1540. VALUES ('".$clean_post_title."',
  1541. '".Database::escape_string($values['forum_id'])."',
  1542. '".Database::escape_string($_user['user_id'])."',
  1543. '".Database::escape_string(isset($values['poster_name'])?$values['poster_name']:null)."',
  1544. '".Database::escape_string($post_date)."',
  1545. '".Database::escape_string(isset($values['thread_sticky'])?$values['thread_sticky']:null)."'," .
  1546. "'".Database::escape_string($values['calification_notebook_title'])."'," .
  1547. "'".Database::escape_string($values['numeric_calification'])."'," .
  1548. "'".Database::escape_string($values['weight_calification'])."'," .
  1549. "'".api_get_session_id()."')";
  1550. $result=api_sql_query($sql, __LINE__, __FILE__);
  1551. $last_thread_id=Database::insert_id();
  1552. //add option gradebook qualify
  1553. if(isset($values['thread_qualify_gradebook']) && 1==$values['thread_qualify_gradebook']) {
  1554. //add function gradebook
  1555. $coursecode=api_get_course_id();
  1556. $resourcetype=5;
  1557. $resourceid=$last_thread_id;
  1558. $resourcename=$values['calification_notebook_title'];
  1559. $maxqualify=$values['numeric_calification'];
  1560. $weigthqualify=$values['weight_calification'];
  1561. $resourcedescription='';
  1562. $date=time();
  1563. //is_resource_in_course_gradebook($course_code, $resource_type, $resource_id);
  1564. add_resource_to_course_gradebook($coursecode,$resourcetype,$resourceid,$resourcename,$weigthqualify,$maxqualify,$resourcedescription,$date,0,api_get_session_id());
  1565. }
  1566. api_item_property_update($_course, TOOL_FORUM_THREAD, $last_thread_id,"ForumThreadAdded", api_get_user_id());
  1567. // if the forum properties tell that the posts have to be approved we have to put the whole thread invisible
  1568. // because otherwise the students will see the thread and not the post in the thread.
  1569. // we also have to change $visible because the post itself has to be visible in this case (otherwise the teacher would have
  1570. // to make the thread visible AND the post
  1571. if ($visible==0) {
  1572. api_item_property_update($_course, TOOL_FORUM_THREAD, $last_thread_id,"invisible", api_get_user_id());
  1573. $visible=1;
  1574. }
  1575. // We now store the content in the table_post table
  1576. $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)
  1577. VALUES ('".$clean_post_title."',
  1578. '".Database::escape_string($values['post_text'])."',
  1579. '".Database::escape_string($last_thread_id)."',
  1580. '".Database::escape_string($values['forum_id'])."',
  1581. '".Database::escape_string($_user['user_id'])."',
  1582. '".Database::escape_string(isset($values['poster_name'])?$values['poster_name']:null)."',
  1583. '".Database::escape_string($post_date)."',
  1584. '".Database::escape_string(isset($values['post_notification'])?$values['post_notification']:null)."','0',
  1585. '".Database::escape_string($visible)."')";
  1586. api_sql_query($sql, __FILE__,__LINE__);
  1587. $last_post_id=Database::insert_id();
  1588. // 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)
  1589. $sql="UPDATE $table_threads SET thread_last_post='".Database::escape_string($last_post_id)."' WHERE thread_id='".Database::escape_string($last_thread_id)."'";
  1590. $result=api_sql_query($sql, __LINE__, __FILE__);
  1591. $message=get_lang('NewThreadStored');
  1592. // Storing the attachments if any
  1593. if ($has_attachment) {
  1594. $courseDir = $_course['path'].'/upload/forum';
  1595. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  1596. $updir = $sys_course_path.$courseDir;
  1597. // Try to add an extension to the file if it hasn't one
  1598. $new_file_name = add_ext_on_mime(stripslashes($_FILES['user_upload']['name']), $_FILES['user_upload']['type']);
  1599. // user's file name
  1600. $file_name =$_FILES['user_upload']['name'];
  1601. if (!filter_extension($new_file_name)) {
  1602. Display :: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
  1603. } else {
  1604. $new_file_name = uniqid('');
  1605. $new_path=$updir.'/'.$new_file_name;
  1606. $result= @move_uploaded_file($_FILES['user_upload']['tmp_name'], $new_path);
  1607. $comment=$values['file_comment'];
  1608. // Storing the attachments if any
  1609. if ($result) {
  1610. $sql='INSERT INTO '.$forum_table_attachment.'(filename,comment, path, post_id,size) '.
  1611. "VALUES ( '".Database::escape_string($file_name)."', '".Database::escape_string($comment)."', '".Database::escape_string($new_file_name)."' , '".$last_post_id."', '".$_FILES['user_upload']['size']."' )";
  1612. $result=api_sql_query($sql, __LINE__, __FILE__);
  1613. $message.=' / '.get_lang('FileUploadSucces').'<br />';
  1614. $last_id=Database::insert_id();
  1615. api_item_property_update($_course, TOOL_FORUM_ATTACH, $last_id ,'ForumAttachmentAdded', api_get_user_id());
  1616. }
  1617. }
  1618. } else {
  1619. $message.='<br />';
  1620. }
  1621. if ($current_forum['approval_direct_post']=='1' AND !api_is_allowed_to_edit()) {
  1622. $message.=get_lang('MessageHasToBeApproved').'<br />';
  1623. $message.=get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&gidReq='.$_SESSION['toolgroup'].'&origin='.$origin.'">'.get_lang('Forum').'</a><br />';
  1624. } else {
  1625. $message.=get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&gidReq='.$_SESSION['toolgroup'].'&origin='.$origin.'">'.get_lang('Forum').'</a><br />';
  1626. $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>';
  1627. }
  1628. $reply_info['new_post_id'] = $last_post_id;
  1629. $my_post_notification=isset($values['post_notification']) ? $values['post_notification'] : null;
  1630. if ($my_post_notification == 1) {
  1631. set_notification('thread',$last_thread_id, true);
  1632. }
  1633. send_notification_mails($last_thread_id,$reply_info);
  1634. session_unregister('formelements');
  1635. session_unregister('origin');
  1636. session_unregister('breadcrumbs');
  1637. session_unregister('addedresource');
  1638. session_unregister('addedresourceid');
  1639. Display :: display_confirmation_message($message,false);
  1640. } else {
  1641. Display::display_error_message(get_lang('UplNoFileUploaded'));
  1642. }
  1643. }
  1644. /**
  1645. * This function displays the form that is used to add a post. This can be a new thread or a reply.
  1646. * @param $action is the parameter that determines if we are
  1647. * 1. newthread: adding a new thread (both empty) => No I-frame
  1648. * 2. replythread: Replying to a thread ($action = replythread) => I-frame with the complete thread (if enabled)
  1649. * 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)
  1650. * 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)
  1651. *
  1652. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1653. * @version february 2006, dokeos 1.8
  1654. */
  1655. function show_add_post_form($action='', $id='', $form_values='') {
  1656. global $forum_setting;
  1657. global $current_forum;
  1658. global $_user;
  1659. global $origin;
  1660. global $charset;
  1661. // initiate the object
  1662. $my_thread = isset($_GET['thread']) ? $_GET['thread']:'';
  1663. $my_forum = isset($_GET['forum']) ? $_GET['forum']:'';
  1664. $my_action = isset($_GET['action']) ? $_GET['action']:'';
  1665. $my_post = isset($_GET['post']) ? $_GET['post']:'';
  1666. $my_gradebook = isset($_GET['gradebook']) ? $_GET['gradebook']:'';
  1667. $form = new FormValidator('thread', 'post', api_get_self().'?forum='.Security::remove_XSS($my_forum).'&thread='.Security::remove_XSS($my_thread).'&post='.Security::remove_XSS($my_post).'&action='.Security::remove_XSS($my_action).'&origin='.$origin);
  1668. $form->setConstants(array('forum' => '5'));
  1669. // settting the form elements
  1670. $form->addElement('hidden', 'forum_id', strval(intval($my_forum)));
  1671. $form->addElement('hidden', 'thread_id', strval(intval($my_thread)));
  1672. $form->addElement('hidden', 'gradebook', $my_gradebook);
  1673. // if anonymous posts are allowed we also display a form to allow the user to put his name or username in
  1674. if ($current_forum['allow_anonymous']==1 AND !isset($_user['user_id'])) {
  1675. $form->addElement('text', 'poster_name', get_lang('Name'));
  1676. }
  1677. $form->addElement('text', 'post_title', get_lang('Title'),'class="input_titles"');
  1678. $form->addElement('html_editor', 'post_text', get_lang('Text'));
  1679. if ($forum_setting['allow_post_notificiation'] AND isset($_user['user_id'])) {
  1680. $form->addElement('checkbox', 'post_notification', '', get_lang('NotifyByEmail').' ('.$_user['mail'].')');
  1681. }
  1682. if ($forum_setting['allow_sticky'] AND api_is_allowed_to_edit() AND $action=='newthread') {
  1683. $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
  1684. }
  1685. if ($current_forum['allow_attachments']=='1' OR api_is_allowed_to_edit()) {
  1686. //$form->add_resource_button();
  1687. $values = $form->exportValues();
  1688. }
  1689. // user upload
  1690. $form->addElement('html','<br /><b><div class="row"><div class="label">'.get_lang('AddAnAttachment').'</div></div></b><br /><br />');
  1691. $form->addElement('file','user_upload',get_lang('FileName'),'');
  1692. $form->addElement('textarea','file_comment',get_lang('FileComment'),array ('rows' => 4, 'cols' => 34));
  1693. $userid =api_get_user_id();
  1694. $info =api_get_user_info($userid);
  1695. $courseid=api_get_course_id();
  1696. if( (api_is_course_admin() || api_is_course_coach() || api_is_course_tutor()) && !($my_thread) ){
  1697. // thread qualify
  1698. $form->addElement('static','Group','<a href="javascript://" onclick="if(document.getElementById(\'id_qualify\').style.display==\'none\'){ document.getElementById(\'id_qualify\').style.display=\'block\'; } else { document.getElementById(\'id_qualify\').style.display=\'none\'; }" ><br /><img src="../img/nolines_plus.gif" alt="" />'.get_lang('AdvancedParameters').'</a>');
  1699. $form->addElement('html','<div id="id_qualify" style="display:none">');
  1700. $form->addElement('static','Group', '<br /><strong>'.get_lang('AlterQualifyThread').'</strong>');
  1701. $form->addElement('checkbox', 'thread_qualify_gradebook', '', get_lang('QualifyThreadGradebook'));
  1702. $form->addElement('text', 'calification_notebook_title', get_lang('TitleColumnGradebook'));
  1703. $form->addElement('text', 'weight_calification', get_lang('QualifyWeight'),'Style="width:40px"');
  1704. $form->addElement('text', 'numeric_calification', get_lang('QualifyNumeric'),'Style="width:40px"');
  1705. $form->addElement('html','</div>');
  1706. }
  1707. $form->addElement('submit', 'SubmitPost', get_lang('Ok'));
  1708. $form->add_real_progress_bar('DocumentUpload','user_upload');
  1709. if ( !empty($form_values) ) {
  1710. $defaults['post_title']=prepare4display(Security::remove_XSS($form_values['post_title']));
  1711. $defaults['post_text']=prepare4display(Security::remove_XSS($form_values['post_text']));
  1712. $defaults['post_notification']=Security::remove_XSS($form_values['post_notification']);
  1713. $defaults['thread_sticky']=Security::remove_XSS($form_values['thread_sticky']);
  1714. }
  1715. // if we are quoting a message we have to retrieve the information of the post we are quoting so that
  1716. // we can add this as default to the textarea
  1717. if (($action=='quote' || $action=='replymessage') && isset($my_post)) {
  1718. // 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 !!!)
  1719. $form->addElement('hidden', 'post_parent_id', strval(intval($my_post))); // note this has to be cleaned first
  1720. // if we are replying or are quoting then we display a default title.
  1721. $values=get_post_information($my_post); // note: this has to be cleaned first
  1722. $defaults['post_title']=get_lang('ReplyShort').html_entity_decode($values['post_title'],ENT_QUOTES,$charset);
  1723. // When we are quoting a message then we have to put that message into the wysiwyg editor.
  1724. // note: the style has to be hardcoded here because using class="quote" didn't work
  1725. if($action=='quote') {
  1726. $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>';
  1727. }
  1728. }
  1729. $form->setDefaults(isset($defaults)?$defaults:null);
  1730. // the course admin can make a thread sticky (=appears with special icon and always on top)
  1731. $form->addRule('post_title', '<div class="required">'.get_lang('ThisFieldIsRequired'), 'required');
  1732. if ($current_forum['allow_anonymous']==1 AND !isset($_user['user_id'])) {
  1733. $form->addRule('poster_name', '<div class="required">'.get_lang('ThisFieldIsRequired'), 'required');
  1734. }
  1735. // The validation or display
  1736. if( $form->validate() ) {
  1737. $check = Security::check_token('post');
  1738. if ($check) {
  1739. $values = $form->exportValues();
  1740. Security::clear_token();
  1741. return $values;
  1742. }
  1743. } else {
  1744. $token = Security::get_token();
  1745. $form->addElement('hidden','sec_token');
  1746. $form->setConstants(array('sec_token' => $token));
  1747. $form->display();
  1748. echo '<br />';
  1749. if ($forum_setting['show_thread_iframe_on_reply'] and $action<>'newthread') {
  1750. echo "<iframe src=\"iframe_thread.php?forum=".Security::remove_XSS($my_forum)."&amp;thread=".Security::remove_XSS($my_thread)."#".Security::remove_XSS($my_post)."\" width=\"80%\"></iframe>";
  1751. }
  1752. }
  1753. }
  1754. /**
  1755. * @param integer contains the information of user id
  1756. * @param integer contains the information of thread id
  1757. * @param integer contains the information of thread qualify
  1758. * @param integer contains the information of user id of qualifier
  1759. * @param integer contains the information of time
  1760. * @param integer contains the information of session id
  1761. * @return Array() optional
  1762. * @author Isaac Flores <isaac.flores@dokeos.com>, U.N.A.S University
  1763. * @version October 2008, dokeos 1.8.6
  1764. **/
  1765. function store_theme_qualify($user_id,$thread_id,$thread_qualify=0,$qualify_user_id=0,$qualify_time,$session_id=null) {
  1766. $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY,'');
  1767. $table_threads =Database::get_course_table(TABLE_FORUM_THREAD,'');
  1768. if ($user_id==strval(intval($user_id)) && $thread_id==strval(intval($thread_id)) && $thread_qualify==strval(intval($thread_qualify))) {
  1769. //testing
  1770. $sql_string="SELECT thread_qualify_max FROM ". $table_threads ." WHERE thread_id=".$thread_id.";";
  1771. $res_string=api_sql_query($sql_string,__FILE__,__LINE__);
  1772. $row_string=Database::fetch_array($res_string);
  1773. if ($thread_qualify<=$row_string[0]) {
  1774. $sql1="SELECT COUNT(*) FROM ".$table_threads_qualify." WHERE user_id=".$user_id." and thread_id=".$thread_id.";";
  1775. $res1=api_sql_query($sql1);
  1776. $row=Database::fetch_array($res1);
  1777. if ($row[0]==0) {
  1778. $sql="INSERT INTO $table_threads_qualify (user_id," .
  1779. "thread_id,qualify,qualify_user_id,qualify_time,session_id)" .
  1780. "VALUES('".$user_id."','".$thread_id."','".$thread_qualify."'," .
  1781. "'".$qualify_user_id."','".$qualify_time."','".$session_id."')";
  1782. $res=api_sql_query($sql,__FILE__,__LINE__);
  1783. return $res;
  1784. } else {
  1785. $sql1="SELECT qualify FROM ".$table_threads_qualify." WHERE user_id=".$user_id." and thread_id=".$thread_id.";";
  1786. $rs=api_sql_query($sql1,__FILE__,__LINE__);
  1787. $row=Database::fetch_array($rs);
  1788. $row[1]="update";
  1789. return $row;
  1790. }
  1791. }else{
  1792. return null;
  1793. }
  1794. }
  1795. }
  1796. /**
  1797. * This function show qualify.
  1798. * @param string contains the information of option to run
  1799. * @param string contains the information the current course id
  1800. * @param integer contains the information the current forum id
  1801. * @param integer contains the information the current user id
  1802. * @param integer contains the information the current thread id
  1803. * @return integer qualify
  1804. * @example $option=1 obtained the qualification of the current thread
  1805. * @author Isaac Flores <isaac.flores@dokeos.com>, U.N.A.S University
  1806. * @version October 2008, dokeos 1.8.6
  1807. */
  1808. function show_qualify($option,$couser_id,$forum_id,$user_id,$thread_id){
  1809. $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY,'');
  1810. $table_threads =Database::get_course_table(TABLE_FORUM_THREAD,'');
  1811. if ($user_id==strval(intval($user_id)) && $thread_id==strval(intval($thread_id)) && $option==1) {
  1812. $sql="SELECT qualify FROM ".$table_threads_qualify." WHERE user_id=".$user_id." and thread_id=".$thread_id.";";
  1813. $rs=api_sql_query($sql,__FILE__,__LINE__);
  1814. $row=Database::fetch_array($rs);
  1815. return $row[0];
  1816. }
  1817. if ($user_id==strval(intval($user_id)) && $option==2) {
  1818. $sql="SELECT thread_qualify_max FROM ".$table_threads." WHERE thread_id=".$thread_id.";";
  1819. $rs=api_sql_query($sql,__FILE__,__LINE__);
  1820. $row=Database::fetch_array($rs);
  1821. return $row[0];
  1822. }
  1823. }
  1824. /**
  1825. *
  1826. * This function get qualify historical.
  1827. * @param integer contains the information the current user id
  1828. * @param integer contains the information the current thread id
  1829. * @param boolean contains the information of option to run
  1830. * @return array()
  1831. * @author Christian Fasanando <christian.fasanando@dokeos.com>,
  1832. * @author Isaac Flores <isaac.flores@dokeos.com>,
  1833. * @version October 2008, dokeos 1.8.6
  1834. */
  1835. function get_historical_qualify($user_id,$thread_id,$opt) {
  1836. $my_qualify_log=array();
  1837. $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG,'');
  1838. $opt = Database::escape_string($opt);
  1839. if ($opt=='false') {
  1840. $sql="SELECT * FROM ".$table_threads_qualify_log." WHERE thread_id='".Database::escape_string($thread_id)."' and user_id='".Database::escape_string($user_id)."' ORDER BY qualify_time";
  1841. } else {
  1842. $sql="SELECT * FROM ".$table_threads_qualify_log." WHERE thread_id='".Database::escape_string($thread_id)."' and user_id='".Database::escape_string($user_id)."' ORDER BY qualify_time DESC";
  1843. }
  1844. $rs=api_sql_query($sql,__FILE__,__LINE__);
  1845. while ($row=Database::fetch_array($rs,'ASSOC')) {
  1846. $my_qualify_log[]=$row;
  1847. }
  1848. return $my_qualify_log;
  1849. }
  1850. /**
  1851. *
  1852. * This function store qualify historical.
  1853. * @param boolean contains the information of option to run
  1854. * @param string contains the information the current course id
  1855. * @param integer contains the information the current forum id
  1856. * @param integer contains the information the current user id
  1857. * @param integer contains the information the current thread id
  1858. * @param integer contains the information the current qualify
  1859. * @return void
  1860. * @example $option=1 obtained the qualification of the current thread
  1861. * @author Isaac Flores <isaac.flores@dokeos.com>, U.N.A.S University
  1862. * @version October 2008, dokeos 1.8.6
  1863. */
  1864. function store_qualify_historical($option,$couser_id,$forum_id,$user_id,$thread_id,$current_qualify,$qualify_user_id) {
  1865. $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY,'');
  1866. $table_threads =Database::get_course_table(TABLE_FORUM_THREAD,'');
  1867. $table_threads_qualify_log=Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG,'');
  1868. $current_date=date('Y-m-d H:i:s');
  1869. if ($user_id==strval(intval($user_id)) && $thread_id==strval(intval($thread_id)) && $option==1) {
  1870. //extract information of thread_qualify
  1871. $sql="SELECT qualify,qualify_time FROM ".$table_threads_qualify." WHERE user_id=".$user_id." and thread_id=".$thread_id.";";
  1872. $rs=api_sql_query($sql,__FILE__,__LINE__);
  1873. $row=Database::fetch_array($rs);
  1874. //insert thread_historical
  1875. $sql1="INSERT INTO $table_threads_qualify_log (user_id," .
  1876. "thread_id,qualify,qualify_user_id,qualify_time,session_id)" .
  1877. "VALUES('".$user_id."','".$thread_id."','".$row[0]."'," .
  1878. "'".$qualify_user_id."','".$row[1]."','')";
  1879. api_sql_query($sql1,__FILE__,__LINE__);
  1880. //update
  1881. $sql2="UPDATE ".$table_threads_qualify." SET qualify=".$current_qualify.",qualify_time='".$current_date."' WHERE user_id=".$user_id." and thread_id=".$thread_id.";";
  1882. api_sql_query($sql2,__FILE__,__LINE__);
  1883. }
  1884. }
  1885. /**
  1886. *
  1887. * This function show current thread qualify .
  1888. * @param integer contains the information the current thread id
  1889. * @param integer contains the information the current session id
  1890. * @return integer
  1891. * @author Isaac Flores <isaac.flores@dokeos.com>, U.N.A.S University
  1892. * @version December 2008, dokeos 1.8.6
  1893. */
  1894. function current_qualify_of_thread($thread_id,$session_id) {
  1895. $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY,'');
  1896. $res=api_sql_query('SELECT qualify FROM '.$table_threads_qualify.' WHERE thread_id='.$thread_id.' AND session_id='.$session_id);
  1897. $row=Database::fetch_array($res,'ASSOC');
  1898. return $row['qualify'];
  1899. }
  1900. /**
  1901. * This function stores a reply in the forum_post table.
  1902. * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date)
  1903. *
  1904. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1905. * @version february 2006, dokeos 1.8
  1906. */
  1907. function store_reply($values) {
  1908. global $table_threads;
  1909. global $table_posts;
  1910. global $forum_table_attachment;
  1911. global $_user;
  1912. global $_course;
  1913. global $current_forum;
  1914. global $origin;
  1915. $post_date=date('Y-m-d H:i:s');
  1916. if ($current_forum['approval_direct_post']=='1' AND !api_is_allowed_to_edit()) {
  1917. $visible=0; // the post is not approved yet.
  1918. } else {
  1919. $visible=1;
  1920. }
  1921. $upload_ok=1;
  1922. $has_attachment=false;
  1923. if (!empty($_FILES['user_upload']['name'])) {
  1924. $upload_ok = process_uploaded_file($_FILES['user_upload']);
  1925. $has_attachment=true;
  1926. }
  1927. if ($upload_ok) {
  1928. // We first store an entry in the forum_post table
  1929. $sql="INSERT INTO $table_posts (post_title, post_text, thread_id, forum_id, poster_id, post_date, post_notification, post_parent_id, visible)
  1930. VALUES ('".Database::escape_string($values['post_title'])."',
  1931. '".Database::escape_string(isset($values['post_text']) ? $values['post_text'] : null)."',
  1932. '".Database::escape_string($values['thread_id'])."',
  1933. '".Database::escape_string($values['forum_id'])."',
  1934. '".Database::escape_string($_user['user_id'])."',
  1935. '".Database::escape_string($post_date)."',
  1936. '".Database::escape_string(isset($values['post_notification'])?$values['post_notification']:null)."',
  1937. '".Database::escape_string(isset($values['post_parent_id'])?$values['post_parent_id']:null)."',
  1938. '".Database::escape_string($visible)."')";
  1939. $result=api_sql_query($sql, __LINE__, __FILE__);
  1940. $new_post_id=Database::insert_id();
  1941. $values['new_post_id']=$new_post_id;
  1942. $message=get_lang('ReplyAdded');
  1943. if ($has_attachment) {
  1944. $courseDir = $_course['path'].'/upload/forum';
  1945. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  1946. $updir = $sys_course_path.$courseDir;
  1947. // Try to add an extension to the file if it hasn't one
  1948. $new_file_name = add_ext_on_mime(stripslashes($_FILES['user_upload']['name']), $_FILES['user_upload']['type']);
  1949. // user's file name
  1950. $file_name =$_FILES['user_upload']['name'];
  1951. if (!filter_extension($new_file_name)) {
  1952. Display :: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
  1953. } else {
  1954. $new_file_name = uniqid('');
  1955. $new_path=$updir.'/'.$new_file_name;
  1956. $result= @move_uploaded_file($_FILES['user_upload']['tmp_name'], $new_path);
  1957. $comment=$values['file_comment'];
  1958. // Storing the attachments if any
  1959. if ($result) {
  1960. $sql='INSERT INTO '.$forum_table_attachment.'(filename,comment, path, post_id,size) '.
  1961. "VALUES ( '".Database::escape_string($file_name)."', '".Database::escape_string($comment)."', '".Database::escape_string($new_file_name)."' , '".$new_post_id."', '".$_FILES['user_upload']['size']."' )";
  1962. $result=api_sql_query($sql, __LINE__, __FILE__);
  1963. $message.=' / '.get_lang('FileUploadSucces');
  1964. $last_id=Database::insert_id();
  1965. api_item_property_update($_course, TOOL_FORUM_ATTACH, $last_id ,'ForumAttachmentAdded', api_get_user_id());
  1966. }
  1967. }
  1968. }
  1969. // update the thread
  1970. update_thread($values['thread_id'], $new_post_id,$post_date);
  1971. // update the forum
  1972. api_item_property_update($_course, TOOL_FORUM, $values['forum_id'],"NewMessageInForum", api_get_user_id());
  1973. if ($current_forum['approval_direct_post']=='1' AND !api_is_allowed_to_edit()) {
  1974. $message.='<br />'.get_lang('MessageHasToBeApproved').'<br />';
  1975. }
  1976. $message.='<br />'.get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&origin='.$origin.'">'.get_lang('Forum').'</a><br />';
  1977. $message.=get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.$values['forum_id'].'&amp;thread='.$values['thread_id'].'&origin='.$origin.'">'.get_lang('Message').'</a>';
  1978. // setting the notification correctly
  1979. $my_post_notification=isset($values['post_notification']) ? $values['post_notification'] :null;
  1980. if ($my_post_notification == 1) {
  1981. set_notification('thread',$values['thread_id'], true);
  1982. }
  1983. send_notification_mails($values['thread_id'], $values);
  1984. session_unregister('formelements');
  1985. session_unregister('origin');
  1986. session_unregister('breadcrumbs');
  1987. session_unregister('addedresource');
  1988. session_unregister('addedresourceid');
  1989. Display :: display_confirmation_message($message,false);
  1990. } else {
  1991. Display::display_error_message(get_lang('UplNoFileUploaded')." ". get_lang('UplSelectFileFirst'));
  1992. }
  1993. }
  1994. /**
  1995. * This function displays the form that is used to edit a post. This can be a new thread or a reply.
  1996. * @param array contains all the information about the current post
  1997. * @param array contains all the information about the current thread
  1998. * @param array contains all info about the current forum (to check if attachments are allowed)
  1999. * @param array contains the default values to fill the form
  2000. * @return void
  2001. *
  2002. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2003. * @version february 2006, dokeos 1.8
  2004. */
  2005. function show_edit_post_form($current_post, $current_thread, $current_forum, $form_values='') {
  2006. global $forum_setting;
  2007. global $_user;
  2008. global $origin;
  2009. // initiate the object
  2010. $form = new FormValidator('edit_post', 'post', api_get_self().'?forum='.Security::remove_XSS($_GET['forum']).'&origin='.$origin.'&thread='.Security::remove_XSS($_GET['thread']).'&post='.Security::remove_XSS($_GET['post']));
  2011. // settting the form elements
  2012. $form->addElement('hidden', 'post_id', $current_post['post_id']);
  2013. $form->addElement('hidden', 'thread_id', $current_thread['thread_id']);
  2014. if ($current_post['post_parent_id']==0) {
  2015. $form->addElement('hidden', 'is_first_post_of_thread', '1');
  2016. }
  2017. $form->addElement('text', 'post_title', get_lang('Title'),'class="input_titles"');
  2018. $form->addElement('html_editor', 'post_text', get_lang('Text'));
  2019. if (!isset($_GET['edit'])) {
  2020. $form->addElement('static','Group','<a href="javascript://" onclick="if(document.getElementById(\'id_qualify\').style.display==\'none\'){ document.getElementById(\'id_qualify\').style.display=\'block\'; } else { document.getElementById(\'id_qualify\').style.display=\'none\'; }" ><br /><img src="../img/nolines_plus.gif" alt="" />'.get_lang('AdvancedParameters').'</a>');
  2021. $form->addElement('html','<div id="id_qualify" style="display:none">');
  2022. $form->addElement('static','Group','<strong>'.get_lang('AlterQualifyThread').'</strong>');
  2023. $form->addElement('checkbox', 'thread_qualify_gradebook', '', get_lang('QualifyThreadGradebook'));
  2024. $defaults['thread_qualify_gradebook']=is_resource_in_course_gradebook(api_get_course_id(),5,$_GET['thread'],api_get_session_id());
  2025. $form->addElement('text', 'calification_notebook_title', get_lang('TitleColumnGradebook'),'value="'.$current_thread['thread_title_qualify'].'"');
  2026. $form->addElement('text', 'weight_calification', get_lang('QualifyWeight'),'value="'.$current_thread['thread_weight'].'" Style="width:40px"');
  2027. $form->addElement('text', 'numeric_calification', get_lang('QualifyNumeric'),'value="'.$current_thread['thread_qualify_max'].'" Style="width:40px"');
  2028. $form->addElement('html','</div>');
  2029. //add gradebook
  2030. }
  2031. if ($forum_setting['allow_post_notificiation']) {
  2032. $form->addElement('checkbox', 'post_notification', '', get_lang('NotifyByEmail').' ('.$current_post['email'].')');
  2033. }
  2034. if ($forum_setting['allow_sticky'] and api_is_allowed_to_edit() and $current_post['post_parent_id']==0) { // the sticky checkbox only appears when it is the first post of a thread
  2035. $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
  2036. if ( $current_thread['thread_sticky']==1 ) {
  2037. $defaults['thread_sticky']=true;
  2038. }
  2039. }
  2040. if ($current_forum['allow_attachments']=='1' OR api_is_allowed_to_edit()) {
  2041. if (empty($form_values) AND !isset($_POST['SubmitPost'])) {
  2042. //edit_added_resources('forum_post',$current_post['post_id']);
  2043. }
  2044. //$form->add_resource_button();
  2045. $values = $form->exportValues();
  2046. }
  2047. $form->addElement('submit', 'SubmitPost', get_lang('Ok'));
  2048. global $charset;
  2049. // setting the default values for the form elements
  2050. $defaults['post_title']=prepare4display(html_entity_decode($current_post['post_title'],ENT_QUOTES,$charset));
  2051. $defaults['post_text']=prepare4display($current_post['post_text']);
  2052. if ( $current_post['post_notification']==1 ) {
  2053. $defaults['post_notification']=true;
  2054. }
  2055. if (!empty($form_values)) {
  2056. $defaults['post_title']=Security::remove_XSS($form_values['post_title']);
  2057. $defaults['post_text']=Security::remove_XSS($form_values['post_text']);
  2058. $defaults['post_notification']=Security::remove_XSS($form_values['post_notification']);
  2059. $defaults['thread_sticky']=Security::remove_XSS($form_values['thread_sticky']);
  2060. }
  2061. $form->setDefaults($defaults);
  2062. // the course admin can make a thread sticky (=appears with special icon and always on top)
  2063. $form->addRule('post_title', '<div class="required">'.get_lang('ThisFieldIsRequired'), 'required');
  2064. // The validation or display
  2065. if( $form->validate() ) {
  2066. $values = $form->exportValues();
  2067. return $values;
  2068. } else {
  2069. $form->display();
  2070. }
  2071. }
  2072. /**
  2073. * This function stores the edit of a post in the forum_post table.
  2074. *
  2075. * @param
  2076. * @return
  2077. *
  2078. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2079. * @version february 2006, dokeos 1.8
  2080. */
  2081. function store_edit_post($values) {
  2082. global $table_threads;
  2083. global $table_posts;
  2084. global $origin;
  2085. // first we check if the change affects the thread and if so we commit the changes (sticky and post_title=thread_title are relevant)
  2086. if (array_key_exists('is_first_post_of_thread',$values) AND $values['is_first_post_of_thread']=='1') {
  2087. $sql="UPDATE $table_threads SET thread_title='".Database::escape_string($values['post_title'])."',
  2088. thread_sticky='".Database::escape_string(isset($values['thread_sticky']) ? $values['thread_sticky'] : null)."'," .
  2089. "thread_title_qualify='".Database::escape_string($values['calification_notebook_title'])."'," .
  2090. "thread_qualify_max='".Database::escape_string($values['numeric_calification'])."',".
  2091. "thread_weight='".Database::escape_string($values['weight_calification'])."'".
  2092. " WHERE thread_id='".Database::escape_string($values['thread_id'])."'";
  2093. api_sql_query($sql,__FILE__, __LINE__);
  2094. }
  2095. // update the post_title and the post_text
  2096. $sql="UPDATE $table_posts SET post_title='".Database::escape_string($values['post_title'])."',
  2097. post_text='".Database::escape_string($values['post_text'])."',
  2098. post_notification='".Database::escape_string(isset($values['post_notification'])?$values['post_notification']:null)."'
  2099. WHERE post_id='".Database::escape_string($values['post_id'])."'";
  2100. //error_log($sql);
  2101. api_sql_query($sql,__FILE__, __LINE__);
  2102. if (api_is_course_admin()==true) {
  2103. $ccode = api_get_course_id();
  2104. $sid = api_get_session_id();
  2105. $link_id = is_resource_in_course_gradebook($ccode,5,$values['thread_id'],$sid);
  2106. $thread_qualify_gradebook=isset($values['thread_qualify_gradebook']) ? $values['thread_qualify_gradebook'] : null;
  2107. if ($thread_qualify_gradebook!=1) {
  2108. if ($link_id !== false) {
  2109. remove_resource_from_course_gradebook($link_id);
  2110. }
  2111. } else {
  2112. if ($link_id === false && !$_GET['thread']) {
  2113. //$date_in_gradebook=date('Y-m-d H:i:s');
  2114. $date_in_gradebook=null;
  2115. $weigthqualify=$values['weight_calification'];
  2116. add_resource_to_course_gradebook($ccode,5,$values['thread_id'],Database::escape_string($values['calification_notebook_title']),$weigthqualify,$values['numeric_calification'],null,$date_in_gradebook,0,$sid);
  2117. }
  2118. }
  2119. }
  2120. // Storing the attachments if any
  2121. //update_added_resources('forum_post',$values['post_id']);
  2122. $message=get_lang('EditPostStored').'<br />';
  2123. $message.=get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&forum='.Security::remove_XSS($_GET['forum']).'&amp;gidReq='.$_SESSION['toolgroup'].'&amp;origin='.$origin.'">'.get_lang('Forum').'</a><br />';
  2124. $message.=get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&forum='.Security::remove_XSS($_GET['forum']).'&amp;gidReq='.$_SESSION['toolgroup'].'&amp;origin='.$origin.'&amp;thread='.$values['thread_id'].'&amp;post='.Security::remove_XSS($_GET['post']).'">'.get_lang('Message').'</a>';
  2125. session_unregister('formelements');
  2126. session_unregister('origin');
  2127. session_unregister('breadcrumbs');
  2128. session_unregister('addedresource');
  2129. session_unregister('addedresourceid');
  2130. Display :: display_confirmation_message($message,false);
  2131. }
  2132. /**
  2133. * This function displays the firstname and lastname of the user as a link to the user tool.
  2134. *
  2135. * @param
  2136. * @return
  2137. *
  2138. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2139. * @version february 2006, dokeos 1.8
  2140. */
  2141. function display_user_link($user_id, $name, $origin='') {
  2142. if ($user_id<>0) {
  2143. return '<a href="../user/userInfo.php?uInfo='.$user_id.'" '. (!empty($origin)? 'target="_top"': '') .'>'.$name.'</a>';
  2144. } else {
  2145. return $name.' ('.get_lang('Anonymous').')';
  2146. }
  2147. }
  2148. /**
  2149. * This function displays the user image from the profile, with a link to the user's details.
  2150. * @param int User's database ID
  2151. * @param str User's name
  2152. * @return string An HTML with the anchor and the image of the user
  2153. * @author Julio Montoya <julio.montoya@dokeos.com>
  2154. */
  2155. function display_user_image($user_id,$name, $origin='') {
  2156. $link='<a href="../user/userInfo.php?uInfo='.$user_id.'" '. (!empty($origin)? 'target="_top"': '') .'>';
  2157. $attrb=array();
  2158. if ($user_id<>0) {
  2159. $image_path = UserManager::get_user_picture_path_by_id($user_id,'web',false, true);
  2160. $image_repository = $image_path['dir'];
  2161. $existing_image = $image_path['file'];
  2162. return $link.'<img src="'.$image_repository.$existing_image.'" alt="'.$name.'" title="'.$name.'" /></a>';
  2163. } else {
  2164. return $link.'<img src="'.api_get_path(WEB_CODE_PATH)."img/unknown.jpg".'" alt="'.$name.'" title="'.$name.'" /></a>';
  2165. }
  2166. }
  2167. /**
  2168. * The thread view counter gets increased every time someone looks at the thread
  2169. *
  2170. * @param
  2171. * @return
  2172. *
  2173. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2174. * @version february 2006, dokeos 1.8
  2175. */
  2176. function increase_thread_view($thread_id) {
  2177. global $table_threads;
  2178. $sql="UPDATE $table_threads SET thread_views=thread_views+1 WHERE thread_id='".Database::escape_string($thread_id)."'"; // this needs to be cleaned first
  2179. $result=api_sql_query($sql, __LINE__, __FILE__);
  2180. }
  2181. /**
  2182. * The relies counter gets increased every time somebody replies to the thread
  2183. *
  2184. * @param
  2185. * @return
  2186. *
  2187. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2188. * @version february 2006, dokeos 1.8
  2189. */
  2190. function update_thread($thread_id, $last_post_id,$post_date) {
  2191. global $table_threads;
  2192. $sql="UPDATE $table_threads SET thread_replies=thread_replies+1,
  2193. thread_last_post='".Database::escape_string($last_post_id)."',
  2194. thread_date='".Database::escape_string($post_date)."' WHERE thread_id='".Database::escape_string($thread_id)."'"; // this needs to be cleaned first
  2195. $result=api_sql_query($sql, __LINE__, __FILE__);
  2196. }
  2197. /**
  2198. * This function is called when the user is not allowed in this forum/thread/...
  2199. *
  2200. * @param
  2201. * @return
  2202. *
  2203. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2204. * @version february 2006, dokeos 1.8
  2205. */
  2206. function forum_not_allowed_here() {
  2207. Display :: display_error_message(get_lang('NotAllowedHere'));
  2208. Display :: display_footer();
  2209. exit;
  2210. }
  2211. /**
  2212. * This function is used to find all the information about what's new in the forum tool
  2213. *
  2214. * @param
  2215. * @return
  2216. *
  2217. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2218. * @version february 2006, dokeos 1.8
  2219. */
  2220. function get_whats_new() {
  2221. global $_user;
  2222. global $_course;
  2223. global $table_posts;
  2224. // note this has later to be replaced by the tool constant. But temporarily bb_forum is used since this is the only thing that is in the tracking currently.
  2225. //$tool=TOOL_FORUM;
  2226. $tool=TOOL_FORUM; //
  2227. // to do: remove this. For testing purposes only
  2228. //session_unregister('last_forum_access');
  2229. //session_unregister('whatsnew_post_info');
  2230. if (!$_SESSION['last_forum_access']) {
  2231. $tracking_last_tool_access=Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
  2232. $sql="SELECT * FROM ".$tracking_last_tool_access." WHERE access_user_id='".Database::escape_string($_user['user_id'])."' AND access_cours_code='".Database::escape_string($_course['sysCode'])."' AND access_tool='".Database::escape_string($tool)."'";
  2233. $result=api_sql_query($sql,__FILE__,__LINE__);
  2234. $row=Database::fetch_array($result);
  2235. $_SESSION['last_forum_access']=$row['access_date'];
  2236. }
  2237. if (!$_SESSION['whatsnew_post_info']) {
  2238. if ($_SESSION['last_forum_access']<>'') {
  2239. $whatsnew_post_info = array();
  2240. $sql="SELECT * FROM".$table_posts."WHERE post_date>'".Database::escape_string($_SESSION['last_forum_access'])."'"; // note: check the performance of this query.
  2241. $result=api_sql_query($sql,__FILE__,__LINE__);
  2242. while ($row=Database::fetch_array($result)) {
  2243. $whatsnew_post_info[$row['forum_id']][$row['thread_id']][$row['post_id']]=$row['post_date'];
  2244. }
  2245. $_SESSION['whatsnew_post_info']=$whatsnew_post_info;
  2246. }
  2247. }
  2248. }
  2249. /**
  2250. * With this function we find the number of posts and topics in a given forum.
  2251. *
  2252. * @param
  2253. * @return
  2254. *
  2255. * @todo consider to call this function only once and let it return an array where the key is the forum id and the value is an array with number_of_topics and number of post
  2256. * as key of this array and the value as a value. This could reduce the number of queries needed (especially when there are more forums)
  2257. * @todo consider merging both in one query.
  2258. *
  2259. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2260. * @version february 2006, dokeos 1.8
  2261. *
  2262. * @deprecated the counting mechanism is now inside the function get_forums
  2263. */
  2264. function get_post_topics_of_forum($forum_id) {
  2265. global $table_posts;
  2266. global $table_threads;
  2267. global $table_item_property;
  2268. $sql="SELECT count(*) as number_of_posts FROM $table_posts WHERE forum_id='".$forum_id."'";
  2269. if (api_is_allowed_to_edit()) {
  2270. $sql="SELECT count(*) as number_of_posts
  2271. FROM $table_posts posts, $table_threads threads, $table_item_property item_property
  2272. WHERE posts.forum_id='".Database::escape_string($forum_id)."'
  2273. AND posts.thread_id=threads.thread_id
  2274. AND item_property.ref=threads.thread_id
  2275. AND item_property.visibility<>2
  2276. AND item_property.tool='".TOOL_FORUM_THREAD."'
  2277. ";
  2278. } else {
  2279. $sql="SELECT count(*) as number_of_posts
  2280. FROM $table_posts posts, $table_threads threads, $table_item_property item_property
  2281. WHERE posts.forum_id='".Database::escape_string($forum_id)."'
  2282. AND posts.thread_id=threads.thread_id
  2283. AND item_property.ref=threads.thread_id
  2284. AND item_property.visibility=1
  2285. AND posts.visible=1
  2286. AND item_property.tool='".TOOL_FORUM_THREAD."'
  2287. ";
  2288. }
  2289. $result=api_sql_query($sql, __FILE__, __LINE__);
  2290. $row=Database::fetch_array($result);
  2291. $number_of_posts=$row['number_of_posts'];
  2292. // we could loop through the result array and count the number of different group_ids but I have chosen to use a second sql statement
  2293. if (api_is_allowed_to_edit()) {
  2294. $sql="SELECT count(*) as number_of_topics
  2295. FROM $table_threads threads, $table_item_property item_property
  2296. WHERE threads.forum_id='".Database::escape_string($forum_id)."'
  2297. AND item_property.ref=threads.thread_id
  2298. AND item_property.visibility<>2
  2299. AND item_property.tool='".TOOL_FORUM_THREAD."'
  2300. ";
  2301. } else {
  2302. $sql="SELECT count(*) as number_of_topics
  2303. FROM $table_threads threads, $table_item_property item_property
  2304. WHERE threads.forum_id='".Database::escape_string($forum_id)."'
  2305. AND item_property.ref=threads.thread_id
  2306. AND item_property.visibility=1
  2307. AND item_property.tool='".TOOL_FORUM_THREAD."'
  2308. ";
  2309. }
  2310. $result=api_sql_query($sql, __FILE__, __LINE__);
  2311. $row=Database::fetch_array($result);
  2312. $number_of_topics=$row['number_of_topics'];
  2313. if ($number_of_topics=='') {
  2314. $number_of_topics=0; // due to the nature of the group by this can result in an empty string.
  2315. }
  2316. $return=array('number_of_topics'=>$number_of_topics, 'number_of_posts'=>$number_of_posts);
  2317. return $return;
  2318. }
  2319. /**
  2320. * This function approves a post = change
  2321. *
  2322. * @param $post_id the id of the post that will be deleted
  2323. * @param $action make the post visible or invisible
  2324. * @return
  2325. *
  2326. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2327. * @version february 2006, dokeos 1.8
  2328. */
  2329. function approve_post($post_id, $action) {
  2330. global $table_posts;
  2331. if ($action=='invisible') {
  2332. $visibility_value=0;
  2333. }
  2334. if ($action=='visible') {
  2335. $visibility_value=1;
  2336. handle_mail_cue('post',$post_id);
  2337. }
  2338. $sql="UPDATE $table_posts SET visible='".Database::escape_string($visibility_value)."' WHERE post_id='".Database::escape_string($post_id)."'";
  2339. $return=api_sql_query($sql, __FILE__, __LINE__);
  2340. if ($return) {
  2341. return 'PostVisibilityChanged';
  2342. }
  2343. }
  2344. /**
  2345. * This function retrieves all the unapproved messages for a given forum
  2346. * This is needed to display the icon that there are unapproved messages in that thread (only the courseadmin can see this)
  2347. *
  2348. * @param $forum_id the forum where we want to know the unapproved messages of
  2349. * @return
  2350. *
  2351. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2352. * @version february 2006, dokeos 1.8
  2353. */
  2354. function get_unaproved_messages($forum_id) {
  2355. global $table_posts;
  2356. $return_array=array();
  2357. $sql="SELECT DISTINCT thread_id FROM $table_posts WHERE forum_id='".Database::escape_string($forum_id)."' AND visible='0'";
  2358. $result=api_sql_query($sql, __FILE__, __LINE__);
  2359. while($row=Database::fetch_array($result)) {
  2360. $return_array[]=$row['thread_id'];
  2361. }
  2362. return $return_array;
  2363. }
  2364. /**
  2365. * This function sends the notification mails to everybody who stated that they wanted to be informed when a new post
  2366. * was added to a given thread.
  2367. *
  2368. * @param
  2369. * @return
  2370. *
  2371. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2372. * @version february 2006, dokeos 1.8
  2373. */
  2374. function send_notification_mails($thread_id, $reply_info) {
  2375. global $table_posts;
  2376. global $table_user;
  2377. global $table_mailcue;
  2378. // First we need to check if
  2379. // 1. the forum category is visible
  2380. // 2. the forum is visible
  2381. // 3. the thread is visible
  2382. // 4. the reply is visible (=when there is
  2383. $current_thread=get_thread_information($thread_id);
  2384. $current_forum=get_forum_information($current_thread['forum_id']);
  2385. $current_forum_category=get_forumcategory_information($current_forum['forum_category']);
  2386. if($current_thread['visibility']=='1' AND $current_forum['visibility']=='1' AND $current_forum_category['visibility']=='1' AND $current_forum['approval_direct_post']!='1') {
  2387. $send_mails=true;
  2388. } else {
  2389. $send_mails=false;
  2390. }
  2391. // the forum category, the forum, the thread and the reply are visible to the user
  2392. if ($send_mails==true) {
  2393. send_notifications($current_thread['forum_id'],$thread_id);
  2394. /*
  2395. $sql="SELECT DISTINCT user.firstname, user.lastname, user.email, user.user_id
  2396. FROM $table_posts post, $table_user user
  2397. WHERE post.thread_id='".Database::escape_string($thread_id)."'
  2398. AND post.post_notification='1'
  2399. AND post.poster_id=user.user_id";
  2400. $result=api_sql_query($sql, __LINE__, __FILE__);
  2401. while ($row=Database::fetch_array($result))
  2402. {
  2403. send_mail($row, $current_thread);
  2404. }
  2405. */
  2406. } else {
  2407. /*
  2408. $sql="SELECT * FROM $table_posts WHERE thread_id='".Database::escape_string($thread_id)."' AND post_notification='1'";
  2409. $result=api_sql_query($sql, __LINE__, __FILE__);
  2410. */
  2411. $table_notification = Database::get_course_table('forum_notification');
  2412. $sql = "SELECT * FROM $table_notification WHERE forum_id = '".Database::escape_string($current_forum['forum_id'])."' OR thread_id = '".Database::escape_string($thread_id)."'";
  2413. $result=api_sql_query($sql, __FILE__, __LINE__);
  2414. while ($row=Database::fetch_array($result)) {
  2415. $sql_mailcue="INSERT INTO $table_mailcue (thread_id, post_id) VALUES ('".Database::escape_string($thread_id)."', '".Database::escape_string($reply_info['new_post_id'])."')";
  2416. $result_mailcue=api_sql_query($sql_mailcue, __LINE__, __FILE__);
  2417. }
  2418. }
  2419. }
  2420. /**
  2421. * This function is called whenever something is made visible because there might be new posts and the user might have indicated that (s)he wanted
  2422. * to be informed about the new posts by mail.
  2423. *
  2424. * @param
  2425. * @return
  2426. *
  2427. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2428. * @version february 2006, dokeos 1.8
  2429. */
  2430. function handle_mail_cue($content, $id) {
  2431. global $table_mailcue;
  2432. global $table_forums;
  2433. global $table_threads;
  2434. global $table_posts;
  2435. global $table_users;
  2436. // if the post is made visible we only have to send mails to the people who indicated that they wanted to be informed for that thread.
  2437. if ($content=='post') {
  2438. // getting the information about the post (need the thread_id)
  2439. $post_info=get_post_information($id);
  2440. // sending the mail to all the users that wanted to be informed for replies on this thread.
  2441. $sql="SELECT users.firstname, users.lastname, users.user_id, users.email FROM $table_mailcue mailcue, $table_posts posts, $table_users users
  2442. WHERE posts.thread_id='".Database::escape_string($post_info['thread_id'])."'
  2443. AND posts.post_notification='1'
  2444. AND mailcue.thread_id='".Database::escape_string($post_info['thread_id'])."'
  2445. AND users.user_id=posts.poster_id
  2446. GROUP BY users.email";
  2447. $result=api_sql_query($sql, __FILE__, __LINE__);
  2448. while ($row=Database::fetch_array($result)) {
  2449. send_mail($row, get_thread_information($post_info['thread_id']));
  2450. }
  2451. // deleting the relevant entries from the mailcue
  2452. $sql_delete_mailcue="DELETE FROM $table_mailcue WHERE post_id='".Database::escape_string($id)."' AND thread_id='".Database::escape_string($post_info['thread_id'])."'";
  2453. //$result=api_sql_query($sql_delete_mailcue, __LINE__, __FILE__);
  2454. } elseif ($content=='thread') {
  2455. // sending the mail to all the users that wanted to be informed for replies on this thread.
  2456. $sql="SELECT users.firstname, users.lastname, users.user_id, users.email FROM $table_mailcue mailcue, $table_posts posts, $table_users users
  2457. WHERE posts.thread_id='".Database::escape_string($id)."'
  2458. AND posts.post_notification='1'
  2459. AND mailcue.thread_id='".Database::escape_string($id)."'
  2460. AND users.user_id=posts.poster_id
  2461. GROUP BY users.email";
  2462. $result=api_sql_query($sql,__FILE__, __LINE__);
  2463. while ($row=Database::fetch_array($result)) {
  2464. send_mail($row, get_thread_information($id));
  2465. }
  2466. // deleting the relevant entries from the mailcue
  2467. $sql_delete_mailcue="DELETE FROM $table_mailcue WHERE thread_id='".Database::escape_string($id)."'";
  2468. $result=api_sql_query($sql_delete_mailcue, __FILE__, __LINE__);
  2469. } elseif ($content=='forum') {
  2470. $sql="SELECT * FROM $table_threads WHERE forum_id='".Database::escape_string($id)."'";
  2471. $result=api_sql_query($sql, __FILE__, __LINE__);
  2472. while ($row=Database::fetch_array($result)) {
  2473. handle_mail_cue('thread',$row['thread_id']);
  2474. }
  2475. } elseif ($content=='forum_category') {
  2476. $sql="SELECT * FROM $table_forums WHERE forum_category ='".Database::escape_string($id)."'";
  2477. $result=api_sql_query($sql, __FILE__, __LINE__);
  2478. while ($row=Database::fetch_array($result)) {
  2479. handle_mail_cue('forum',$row['forum_id']);
  2480. }
  2481. } else {
  2482. return get_lang('Error');
  2483. }
  2484. }
  2485. /**
  2486. * This function sends the mails for the mail notification
  2487. *
  2488. * @param
  2489. * @return
  2490. *
  2491. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2492. * @version february 2006, dokeos 1.8
  2493. */
  2494. function send_mail($user_info=array(), $thread_information=array()) {
  2495. global $_course;
  2496. global $_user;
  2497. $email_subject = get_lang('NewForumPost')." - ".$_course['official_code'];
  2498. if (isset($thread_information) and is_array($thread_information)) {
  2499. $thread_link= api_get_path('WEB_CODE_PATH').'forum/viewthread.php?'.api_get_cidreq().'&forum='.$thread_information['forum_id'].'&thread='.$thread_information['thread_id'];
  2500. }
  2501. $email_body= $user_info['firstname']." ".$user_info['lastname']."\n\r";
  2502. $email_body .= '['.$_course['official_code'].'] - ['.$_course['name']."]<br>\n";
  2503. $email_body .= get_lang('NewForumPost')."\n";
  2504. $email_body .= get_lang('YouWantedToStayInformed')."<br><br>\n";
  2505. $email_body .= get_lang('ThreadCanBeFoundHere')." : <a href=\"".$thread_link."\">".$thread_link."</a>\n";
  2506. //set the charset and use it for the encoding of the email - small fix, not really clean (should check the content encoding origin first)
  2507. //here we use the encoding used for the webpage where the text is encoded (ISO-8859-1 in this case)
  2508. if(empty($charset)) {
  2509. $charset='ISO-8859-1';
  2510. }
  2511. if ($user_info['user_id']<>$_user['user_id']) {
  2512. $newmail = api_mail_html($user_info["lastname"].' '.$user_info["firstname"], $user_info["email"], $email_subject, $email_body, $_SESSION['_user']['lastName'].' '.$_SESSION['_user']['firstName'], $_SESSION['_user']['mail']);
  2513. }
  2514. }
  2515. /**
  2516. * This function displays the form for moving a thread to a different (already existing) forum
  2517. *
  2518. * @param
  2519. * @return
  2520. *
  2521. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2522. * @version february 2006, dokeos 1.8
  2523. */
  2524. function move_thread_form() {
  2525. global $origin;
  2526. // initiate the object
  2527. $form = new FormValidator('movepost', 'post', api_get_self().'?forum='.Security::remove_XSS($_GET['forum']).'&thread='.Security::remove_XSS($_GET['thread']).'&action='.Security::remove_XSS($_GET['action']).'&origin='.$origin);
  2528. // the header for the form
  2529. $form->addElement('header', '', get_lang('MoveThread'));
  2530. // invisible form: the thread_id
  2531. $form->addElement('hidden', 'thread_id', strval(intval($_GET['thread']))); // note: this has to be cleaned first
  2532. // the fora
  2533. $forum_categories=get_forum_categories();
  2534. $forums=get_forums();
  2535. $htmlcontent="\n<tr>\n<td></td>\n<td>\n<SELECT NAME='forum'>\n";
  2536. foreach ($forum_categories as $key=>$category) {
  2537. $htmlcontent.="\t<OPTGROUP LABEL=\"".$category['cat_title']."\">\n";
  2538. foreach ($forums as $key=>$forum) {
  2539. if ($forum['forum_category']==$category['cat_id']) {
  2540. $htmlcontent.="\t\t<OPTION VALUE='".$forum['forum_id']."'>".$forum['forum_title']."</OPTION>\n";
  2541. }
  2542. }
  2543. $htmlcontent.="\t</OPTGROUP>\n";
  2544. }
  2545. $htmlcontent.="</SELECT>\n</td></tr>";
  2546. $form->addElement('html',$htmlcontent);
  2547. // The OK button
  2548. $form->addElement('submit', 'SubmitForum',get_lang('Ok'));
  2549. // The validation or display
  2550. if( $form->validate()) {
  2551. $values = $form->exportValues();
  2552. if (isset($_POST['forum'])) {
  2553. store_move_thread($values);
  2554. }
  2555. } else {
  2556. $form->display();
  2557. }
  2558. }
  2559. /**
  2560. * This function displays the form for moving a post message to a different (already existing) or a new thread.
  2561. *
  2562. * @param
  2563. * @return
  2564. *
  2565. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2566. * @version february 2006, dokeos 1.8
  2567. */
  2568. function move_post_form() {
  2569. global $origin;
  2570. // initiate the object
  2571. $form = new FormValidator('movepost', 'post', api_get_self().'?forum='.Security::remove_XSS($_GET['forum']).'&thread='.Security::remove_XSS($_GET['thread']).'&origin='.$origin.'&post='.Security::remove_XSS($_GET['post']).'&action='.Security::remove_XSS($_GET['action']).'&post='.Security::remove_XSS($_GET['post']));
  2572. // the header for the form
  2573. $form->addElement('header', '', get_lang('MovePost'));
  2574. // invisible form: the post_id
  2575. $form->addElement('hidden', 'post_id', strval(intval($_GET['post']))); // note: this has to be cleaned first
  2576. // dropdown list: Threads of this forum
  2577. $threads=get_threads(strval(intval($_GET['forum']))); // note: this has to be cleaned
  2578. //my_print_r($threads);
  2579. $threads_list[0]=get_lang('ANewThread');
  2580. foreach ($threads as $key=>$value) {
  2581. $threads_list[$value['thread_id']]=$value['thread_title'];
  2582. }
  2583. $form->addElement('select', 'thread', get_lang('MoveToThread'), $threads_list);
  2584. // The OK button
  2585. $form->addElement('submit', '',get_lang('Ok'));
  2586. // setting the rules
  2587. $form->addRule('thread', get_lang('ThisFieldIsRequired'), 'required');
  2588. // The validation or display
  2589. if( $form->validate() ) {
  2590. $values = $form->exportValues();
  2591. store_move_post($values);
  2592. } else {
  2593. $form->display();
  2594. }
  2595. }
  2596. /**
  2597. *
  2598. * @param
  2599. * @return
  2600. *
  2601. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2602. * @version february 2006, dokeos 1.8
  2603. */
  2604. function store_move_post($values) {
  2605. global $table_posts;
  2606. global $table_threads;
  2607. global $table_forums;
  2608. global $_course;
  2609. if ($values['thread']=='0') {
  2610. $current_post=get_post_information($values['post_id']);
  2611. // storing a new thread
  2612. $sql="INSERT INTO $table_threads (thread_title, forum_id, thread_poster_id, thread_poster_name, thread_last_post, thread_date)
  2613. VALUES (
  2614. '".Database::escape_string($current_post['post_title'])."',
  2615. '".Database::escape_string($current_post['forum_id'])."',
  2616. '".Database::escape_string($current_post['poster_id'])."',
  2617. '".Database::escape_string($current_post['poster_name'])."',
  2618. '".Database::escape_string($values['post_id'])."',
  2619. '".Database::escape_string($current_post['post_date'])."'
  2620. )";
  2621. $result=api_sql_query($sql, __FILE__, __LINE__);
  2622. $new_thread_id=Database::get_last_insert_id();
  2623. api_item_property_update($_course, TOOL_FORUM_THREAD, $new_thread_id,"visible", $current_post['poster_id']);
  2624. // moving the post to the newly created thread
  2625. $sql="UPDATE $table_posts SET thread_id='".Database::escape_string($new_thread_id)."', post_parent_id='0' WHERE post_id='".Database::escape_string($values['post_id'])."'";
  2626. $result=api_sql_query($sql,__FILE__, __LINE__);
  2627. //echo $sql.'<br />';
  2628. // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
  2629. $sql="UPDATE $table_posts SET post_parent_id='0' WHERE post_parent_id='".Database::escape_string($values['post_id'])."'";
  2630. $result=api_sql_query($sql, __FILE__, __LINE__);
  2631. //echo $sql.'<br />';
  2632. // updating updating the number of threads in the forum
  2633. $sql="UPDATE $table_forums SET forum_threads=forum_threads+1 WHERE forum_id='".Database::escape_string($current_post['forum_id'])."'";
  2634. $result=api_sql_query($sql, __FILE__, __LINE__);
  2635. //echo $sql.'<br />';
  2636. // resetting the last post of the old thread and decreasing the number of replies and the thread
  2637. $sql="SELECT * FROM $table_posts WHERE thread_id='".Database::escape_string($current_post['thread_id'])."' ORDER BY post_id DESC";
  2638. //echo $sql.'<br />';
  2639. $result=api_sql_query($sql, __FILE__, __LINE__);
  2640. $row=Database::fetch_array($result);
  2641. //my_print_r($row);
  2642. $sql="UPDATE $table_threads SET thread_last_post='".$row['post_id']."', thread_replies=thread_replies-1 WHERE thread_id='".Database::escape_string($current_post['thread_id'])."'";
  2643. $result=api_sql_query($sql, __FILE__, __LINE__);
  2644. //echo $sql.'<br />';
  2645. } else {
  2646. // moving to the chosen thread
  2647. $sql="UPDATE $table_posts SET thread_id='".Database::escape_string($_POST['thread'])."', post_parent_id='0' WHERE post_id='".Database::escape_string($values['post_id'])."'";
  2648. $result=api_sql_query($sql, __FILE__, __LINE__);
  2649. // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
  2650. $sql="UPDATE $table_posts SET post_parent_id='0' WHERE post_parent_id='".Database::escape_string($values['post_id'])."'";
  2651. $result=api_sql_query($sql, __FILE__, __LINE__);
  2652. }
  2653. return get_lang('ThreadMoved');
  2654. }
  2655. /**
  2656. *
  2657. * @param
  2658. * @return
  2659. *
  2660. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2661. * @version february 2006, dokeos 1.8
  2662. */
  2663. function store_move_thread($values) {
  2664. global $table_posts;
  2665. global $table_threads;
  2666. global $table_forums;
  2667. global $_course;
  2668. // change the thread table: setting the forum_id to the new forum
  2669. $sql="UPDATE $table_threads SET forum_id='".Database::escape_string($_POST['forum'])."' WHERE thread_id='".Database::escape_string($_POST['thread_id'])."'";
  2670. $result=api_sql_query($sql, __FILE__, __LINE__);
  2671. // changing all the posts of the thread: setting the forum_id to the new forum
  2672. $sql="UPDATE $table_posts SET forum_id='".Database::escape_string($_POST['forum'])."' WHERE thread_id='".Database::escape_string($_POST['thread_id'])."'";
  2673. $result=api_sql_query($sql, __FILE__, __LINE__);
  2674. return get_lang('ThreadMoved');
  2675. }
  2676. /**
  2677. * Prepares a string or an array of strings for display by stripping slashes
  2678. * @param mixed String or array of strings
  2679. * @return mixed String or array of strings
  2680. *
  2681. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2682. * @version february 2006, dokeos 1.8
  2683. */
  2684. function prepare4display($input='') {
  2685. $highlightcolors = array('yellow', '#33CC33','#3399CC', '#9999FF', '#33CC33');
  2686. if (!is_array($input)) {
  2687. if (!empty($_GET['search'])) {
  2688. if (strstr($_GET['search'],'+')) {
  2689. $search_terms = explode('+',$_GET['search']);
  2690. } else {
  2691. $search_terms[] = trim($_GET['search']);
  2692. }
  2693. $counter = 0;
  2694. foreach ($search_terms as $key=>$search_term) {
  2695. $input = str_replace(trim(html_entity_decode($search_term)),'<span style="background-color: '.$highlightcolors[$counter].'">'.trim(html_entity_decode($search_term)).'</span>',$input);
  2696. $counter++;
  2697. }
  2698. }
  2699. return stripslashes($input);
  2700. } else {
  2701. /*foreach ($input as $key=>$value)
  2702. {
  2703. $returnarray[$key]=stripslashes($value);
  2704. }*/
  2705. $returnarray=array_walk($input, 'stripslashes');
  2706. return $returnarray;
  2707. }
  2708. }
  2709. /**
  2710. * Display the search form for the forum and display the search results
  2711. *
  2712. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  2713. * @version march 2008, dokeos 1.8.5
  2714. */
  2715. function forum_search() {
  2716. global $origin;
  2717. // initiate the object
  2718. $form = new FormValidator('forumsearch','post','forumsearch.php?origin='.$origin.'');
  2719. // settting the form elements
  2720. $form->addElement('header', '', get_lang('ForumSearch'));
  2721. $form->addElement('text', 'search_term', get_lang('SearchTerm'),'class="input_titles"');
  2722. $form->addElement('static', 'search_information', '', get_lang('ForumSearchInformation')/*, $dissertation[$_GET['opleidingsonderdeelcode']]['code']*/);
  2723. $form->addElement('submit', 'SubmitForumCategory', get_lang('Search'));
  2724. // setting the rules
  2725. $form->addRule('search_term', '<div class="required">'.get_lang('ThisFieldIsRequired'), 'required');
  2726. $form->addRule('search_term', get_lang('TooShort'),'minlength',3);
  2727. // The validation or display
  2728. if( $form->validate() ) {
  2729. $values = $form->exportValues();
  2730. $form->setDefaults($values);
  2731. $form->display();
  2732. // display the search results
  2733. display_forum_search_results($values['search_term']);
  2734. } else {
  2735. $form->display();
  2736. }
  2737. }
  2738. /**
  2739. * Display the search results
  2740. *
  2741. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  2742. * @version march 2008, dokeos 1.8.5
  2743. */
  2744. function display_forum_search_results($search_term) {
  2745. global $table_categories, $table_forums, $table_threads, $table_posts;
  2746. global $origin;
  2747. // defining the search strings as an array
  2748. if (strstr($search_term,'+')) {
  2749. $search_terms = explode('+',$search_term);
  2750. } else {
  2751. $search_terms[] = $search_term;
  2752. }
  2753. // search restriction
  2754. foreach ($search_terms as $key => $value) {
  2755. $search_restriction[] = "(posts.post_title LIKE '%".Database::escape_string(trim($value))."%'
  2756. OR posts.post_text LIKE '%".Database::escape_string(trim($value))."%')";
  2757. }
  2758. $sql = "SELECT * FROM $table_posts posts
  2759. WHERE ".implode(' AND ',$search_restriction)."
  2760. /*AND posts.thread_id = threads.thread_id*/
  2761. GROUP BY posts.post_id";
  2762. // getting all the information of the forum categories
  2763. $forum_categories_list=get_forum_categories();
  2764. // getting all the information of the forums
  2765. $forum_list=get_forums();
  2766. $result = api_sql_query($sql, __FILE__, __LINE__);
  2767. while ($row = Database::fetch_array($result,'ASSOC')) {
  2768. $display_result = false;
  2769. /*
  2770. we only show it when
  2771. 1. forum cateogory is visible
  2772. 2. forum is visible
  2773. 3. thread is visible (to do)
  2774. 4. post is visible
  2775. */
  2776. if (!api_is_allowed_to_edit()) {
  2777. if ($forum_categories_list[$row['forum_id']['forum_category']]['visibility'] == '1' AND $forum_list[$row['forum_id']]['visibility'] == '1' AND $row['visible'] == '1') {
  2778. $display_result = true;
  2779. }
  2780. } else {
  2781. $display_result = true;
  2782. }
  2783. if ($display_result == true) {
  2784. $search_results_item = '<li><a href="viewforumcategory.php?forumcategory='.$forum_list[$row['forum_id']]['forum_category'].'&origin='.$origin.'&amp;search='.urlencode($search_term).'">'.$forum_categories_list[$row['forum_id']['forum_category']]['cat_title'].'</a> > ';
  2785. $search_results_item .= '<a href="viewforum.php?forum='.$row['forum_id'].'&amp;origin='.$origin.'&amp;search='.urlencode($search_term).'">'.$forum_list[$row['forum_id']]['forum_title'].'</a> > ';
  2786. //$search_results_item .= '<a href="">THREAD</a> > ';
  2787. $search_results_item .= '<a href="viewthread.php?forum='.$row['forum_id'].'&amp;origin='.$origin.'&amp;thread='.$row['thread_id'].'&amp;search='.urlencode($search_term).'">'.$row['post_title'].'</a>';
  2788. $search_results_item .= '<br />';
  2789. if (strlen($row['post_title']) > 200 ) {
  2790. $search_results_item .= substr(strip_tags($row['post_title']),0,200).'...';
  2791. } else {
  2792. $search_results_item .= $row['post_title'];
  2793. }
  2794. $search_results_item .= '</li>';
  2795. $search_results[] = $search_results_item;
  2796. }
  2797. }
  2798. echo '<div class="row"><div class="form_header">'.count($search_results).' '.get_lang('ForumSearchResults').'</div></div>';
  2799. echo '<ol>';
  2800. if($search_results) {
  2801. echo implode($search_results);
  2802. }
  2803. echo '</ol>';
  2804. }
  2805. /**
  2806. * Return the link to the forum search page
  2807. *
  2808. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  2809. * @version April 2008, dokeos 1.8.5
  2810. */
  2811. function search_link() {
  2812. global $origin;
  2813. $return = '<a href="forumsearch.php?'.api_get_cidreq().'&action=search&origin='.$origin.'"> '.Display::return_icon('search.gif', get_lang('Search')).' '.get_lang('Search').'</a>';
  2814. if (!empty($_GET['search'])) {
  2815. $return .= ': '.Security::remove_XSS($_GET['search']).' ';
  2816. $url = api_get_self().'?';
  2817. foreach ($_GET as $key=>$value) {
  2818. if ($key<>'search') {
  2819. $url_parameter[]=Security::remove_XSS($key).'='.Security::remove_XSS($value);
  2820. }
  2821. }
  2822. $url = $url.implode('&amp;',$url_parameter);
  2823. $return .= '<a href="'.$url.'">'.Display::return_icon('delete.gif', get_lang('RemoveSearchResults')).'</a>';
  2824. }
  2825. return $return;
  2826. }
  2827. /**
  2828. * Show a list with all the attachments according to the post's id
  2829. * @param the post's id
  2830. * @return array with the post info
  2831. * @author Julio Montoya Dokeos
  2832. * @version avril 2008, dokeos 1.8.5
  2833. */
  2834. function get_attachment($post_id) {
  2835. global $forum_table_attachment;
  2836. $row=array();
  2837. $sql = 'SELECT path, filename,comment FROM '. $forum_table_attachment.' WHERE post_id ="'.$post_id.'"';
  2838. $result=api_sql_query($sql, __FILE__, __LINE__);
  2839. if (Database::num_rows($result)!=0) {
  2840. $row=Database::fetch_array($result);
  2841. }
  2842. return $row;
  2843. }
  2844. /**
  2845. * Delete the all the attachments from the DB and the file according to the post's id
  2846. * @param post id
  2847. * @author Julio Montoya Dokeos
  2848. * @version avril 2008, dokeos 1.8.5
  2849. */
  2850. function delete_attachment($id) {
  2851. global $forum_table_attachment;
  2852. global $_course;
  2853. $attach_list=get_attachment($id);
  2854. $sql = 'DELETE FROM '. $forum_table_attachment.' WHERE post_id ="'.$id.'"';
  2855. $result=api_sql_query($sql, __FILE__, __LINE__);
  2856. $courseDir = $_course['path'].'/upload/forum';
  2857. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  2858. $updir = $sys_course_path.$courseDir;
  2859. $my_path =isset($attach_list['path']) ? $attach_list['path'] : null;
  2860. $file =$updir.'/'.$my_path;
  2861. api_item_property_update($_course, TOOL_FORUM_ATTACH, $id ,'ForumAttachmentDelete', api_get_user_id());
  2862. if (Security::check_abs_path($file,$updir) ) {
  2863. @ unlink($file);
  2864. }
  2865. }
  2866. /**
  2867. * This function gets all the forum information of the all the forum of the group
  2868. *
  2869. * @param integer $group_id the id of the group we need the fora of (see forum.forum_of_group)
  2870. * @return array
  2871. *
  2872. * @todo this is basically the same code as the get_forums function. Consider merging the two.
  2873. */
  2874. function get_forums_of_group($group_id) {
  2875. global $table_forums;
  2876. global $table_threads;
  2877. global $table_posts;
  2878. global $table_item_property;
  2879. global $table_users;
  2880. //-------------- Student -----------------//
  2881. // select all the forum information of all forums (that are visible to students)
  2882. $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  2883. WHERE forum.forum_of_group = '".Database::escape_string($group_id)."'
  2884. AND forum.forum_id=item_properties.ref
  2885. AND item_properties.visibility=1
  2886. AND item_properties.tool='".TOOL_FORUM."'
  2887. ORDER BY forum.forum_order ASC";
  2888. // select the number of threads of the forums (only the threads that are visible)
  2889. $sql2="SELECT count(thread_id) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  2890. WHERE threads.thread_id=item_properties.ref
  2891. AND item_properties.visibility=1
  2892. AND item_properties.tool='".TOOL_FORUM_THREAD."'
  2893. GROUP BY threads.forum_id";
  2894. // select the number of posts of the forum (post that are visible and that are in a thread that is visible)
  2895. $sql3="SELECT count(post_id) AS number_of_posts, posts.forum_id FROM $table_posts posts, $table_threads threads, ".$table_item_property." item_properties
  2896. WHERE posts.visible=1
  2897. AND posts.thread_id=threads.thread_id
  2898. AND threads.thread_id=item_properties.ref
  2899. AND item_properties.visibility=1
  2900. AND item_properties.tool='".TOOL_FORUM_THREAD."'
  2901. GROUP BY threads.forum_id";
  2902. //-------------- Course Admin -----------------//
  2903. if (is_allowed_to_edit()) {
  2904. // select all the forum information of all forums (that are not deleted)
  2905. $sql="SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  2906. WHERE forum.forum_of_group = '".Database::escape_string($group_id)."'
  2907. AND forum.forum_id=item_properties.ref
  2908. AND item_properties.visibility<>2
  2909. AND item_properties.tool='".TOOL_FORUM."'
  2910. ORDER BY forum_order ASC";
  2911. //echo $sql.'<hr>';
  2912. // select the number of threads of the forums (only the threads that are not deleted)
  2913. $sql2="SELECT count(thread_id) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  2914. WHERE threads.thread_id=item_properties.ref
  2915. AND item_properties.visibility<>2
  2916. AND item_properties.tool='".TOOL_FORUM_THREAD."'
  2917. GROUP BY threads.forum_id";
  2918. //echo $sql2.'<hr>';
  2919. // select the number of posts of the forum
  2920. $sql3="SELECT count(post_id) AS number_of_posts, forum_id FROM $table_posts GROUP BY forum_id";
  2921. //echo $sql3.'<hr>';
  2922. }
  2923. // handling all the forum information
  2924. $result=api_sql_query($sql, __FILE__, __LINE__);
  2925. while ($row=Database::fetch_array($result,'ASSOC')) {
  2926. $forum_list[$row['forum_id']]=$row;
  2927. }
  2928. // handling the threadcount information
  2929. $result2=api_sql_query($sql2, __FILE__, __LINE__);
  2930. while ($row2=Database::fetch_array($result2,'ASSOC')) {
  2931. if (is_array($forum_list)) {
  2932. if (array_key_exists($row2['forum_id'],$forum_list)) {
  2933. $forum_list[$row2['forum_id']]['number_of_threads']=$row2['number_of_threads'];
  2934. }
  2935. }
  2936. }
  2937. // handling the postcount information
  2938. $result3=api_sql_query($sql3, __FILE__, __LINE__);
  2939. while ($row3=Database::fetch_array($result3,'ASSOC')) {
  2940. if (is_array($forum_list)) {
  2941. if (array_key_exists($row3['forum_id'],$forum_list)) {// this is needed because sql3 takes also the deleted forums into account
  2942. $forum_list[$row3['forum_id']]['number_of_posts']=$row3['number_of_posts'];
  2943. }
  2944. }
  2945. }
  2946. // finding the last post information (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname)
  2947. if (is_array($forum_list)) {
  2948. foreach ($forum_list as $key=>$value) {
  2949. $last_post_info_of_forum=get_last_post_information($key,is_allowed_to_edit());
  2950. $forum_list[$key]['last_post_id']=$last_post_info_of_forum['last_post_id'];
  2951. $forum_list[$key]['last_poster_id']=$last_post_info_of_forum['last_poster_id'];
  2952. $forum_list[$key]['last_post_date']=$last_post_info_of_forum['last_post_date'];
  2953. $forum_list[$key]['last_poster_name']=$last_post_info_of_forum['last_poster_name'];
  2954. $forum_list[$key]['last_poster_lastname']=$last_post_info_of_forum['last_poster_lastname'];
  2955. $forum_list[$key]['last_poster_firstname']=$last_post_info_of_forum['last_poster_firstname'];
  2956. }
  2957. }
  2958. return $forum_list;
  2959. }
  2960. /**
  2961. * This function stores which users have to be notified of which forums or threads
  2962. *
  2963. * @param string $content does the user want to be notified about a forum or about a thread
  2964. * @param integer $id the id of the forum or thread
  2965. *
  2966. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  2967. * @version May 2008, dokeos 1.8.5
  2968. * @since May 2008, dokeos 1.8.5
  2969. */
  2970. function set_notification($content,$id, $add_only = false) {
  2971. global $_user;
  2972. // which database field do we have to store the id in?
  2973. if ($content == 'forum') {
  2974. $database_field = 'forum_id';
  2975. } else {
  2976. $database_field = 'thread_id';
  2977. }
  2978. // database table definition
  2979. $table_notification = Database::get_course_table('forum_notification');
  2980. // first we check if the notification is already set for this
  2981. $sql = "SELECT * FROM $table_notification WHERE $database_field = '".Database::escape_string($id)."' AND user_id = '".Database::escape_string($_user['user_id'])."'";
  2982. $result=api_sql_query($sql, __FILE__, __LINE__);
  2983. $total = mysql_num_rows($result);
  2984. // if the user did not indicate that (s)he wanted to be notified already then we store the notification request (to prevent double notification requests)
  2985. if ($total <= 0) {
  2986. $sql = "INSERT INTO $table_notification ($database_field, user_id) VALUES ('".Database::escape_string($id)."','".Database::escape_string($_user['user_id'])."')";
  2987. $result=api_sql_query($sql, __FILE__, __LINE__);
  2988. api_session_unregister('forum_notification');
  2989. get_notifications_of_user(0,true);
  2990. return get_lang('YouWillBeNotifiedOfNewPosts');
  2991. } else {
  2992. if (!$add_only) {
  2993. $sql = "DELETE FROM $table_notification WHERE $database_field = '".Database::escape_string($id)."' AND user_id = '".Database::escape_string($_user['user_id'])."'";
  2994. $result=api_sql_query($sql, __FILE__, __LINE__);
  2995. api_session_unregister('forum_notification');
  2996. get_notifications_of_user(0,true);
  2997. return get_lang('YouWillNoLongerBeNotifiedOfNewPosts');
  2998. }
  2999. }
  3000. }
  3001. /**
  3002. * This function retrieves all the email adresses of the users who wanted to be notified
  3003. * about a new post in a certain forum or thread
  3004. *
  3005. * @param string $content does the user want to be notified about a forum or about a thread
  3006. * @param integer $id the id of the forum or thread
  3007. *
  3008. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  3009. * @version May 2008, dokeos 1.8.5
  3010. * @since May 2008, dokeos 1.8.5
  3011. */
  3012. function get_notifications($content,$id) {
  3013. global $table_users;
  3014. // which database field contains the notification?
  3015. if ($content == 'forum') {
  3016. $database_field = 'forum_id';
  3017. } else {
  3018. $database_field = 'thread_id';
  3019. }
  3020. // database table definition
  3021. $table_notification = Database::get_course_table('forum_notification');
  3022. $sql = "SELECT user.user_id, user.firstname, user.lastname, user.email, user.user_id user FROM $table_users user, $table_notification notification
  3023. WHERE user.user_id = notification.user_id
  3024. AND notification.$database_field= '".Database::escape_string($id)."'";
  3025. $result=api_sql_query($sql, __FILE__, __LINE__);
  3026. $return = array();
  3027. while ($row=Database::fetch_array($result)) {
  3028. $return['user'.$row['user_id']]=array('email' => $row['email'], 'user_id' => $row['user_id']);
  3029. }
  3030. return $return;
  3031. }
  3032. /**
  3033. * Get all the users who need to receive a notification of a new post (those subscribed to
  3034. * the forum or the thread)
  3035. *
  3036. * @param integer $forum_id the id of the forum
  3037. * @param integer $thread_id the id of the thread
  3038. * @param integer $post_id the id of the post
  3039. * @return unknown
  3040. *
  3041. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  3042. * @version May 2008, dokeos 1.8.5
  3043. * @since May 2008, dokeos 1.8.5
  3044. */
  3045. function send_notifications($forum_id=0, $thread_id=0, $post_id=0) {
  3046. global $_course;
  3047. // the content of the mail
  3048. $email_subject = get_lang('NewForumPost')." - ".$_course['official_code'];
  3049. $thread_link= api_get_path('WEB_CODE_PATH').'forum/viewthread.php?'.api_get_cidreq().'&forum='.$forum_id.'&thread='.$thread_id;
  3050. $my_link=isset($link)?$link:'';
  3051. $my_message=isset($message)?$message:'';
  3052. $my_message .= $my_link;
  3053. // users who subscribed to the forum
  3054. if ($forum_id<>0) {
  3055. $users_to_be_notified_by_forum = get_notifications('forum',$forum_id);
  3056. } else {
  3057. return false;
  3058. }
  3059. // user who subscribed to the thread
  3060. if ($thread_id<>0) {
  3061. $users_to_be_notified_by_thread = get_notifications('thread',$thread_id);
  3062. }
  3063. // merging the two
  3064. $users_to_be_notified = array_merge($users_to_be_notified_by_forum, $users_to_be_notified_by_thread);
  3065. if (is_array($users_to_be_notified)) {
  3066. foreach ($users_to_be_notified as $key=>$value) {
  3067. if ($value['email'] <> $_user['email']) {
  3068. $email_body= $value['firstname']." ".$value['lastname']."\n\r";
  3069. $email_body .= '['.$_course['official_code'].'] - ['.$_course['name']."]<br>\n";
  3070. $email_body .= get_lang('NewForumPost')."\n";
  3071. $email_body .= get_lang('YouWantedToStayInformed')."<br><br>\n";
  3072. $email_body .= get_lang('ThreadCanBeFoundHere')." : <a href=\"".$thread_link."\">".$thread_link."</a>\n";
  3073. //set the charset and use it for the encoding of the email - small fix, not really clean (should check the content encoding origin first)
  3074. //here we use the encoding used for the webpage where the text is encoded (ISO-8859-1 in this case)
  3075. if(empty($charset)) {
  3076. $charset='ISO-8859-1';
  3077. }
  3078. $newmail = api_mail_html($value['lastname'].' '.$value['firstname'], $value['email'], $email_subject, $email_body, $_SESSION['_user']['lastName'].' '.$_SESSION['_user']['firstName'], $_SESSION['_user']['mail']);
  3079. }
  3080. }
  3081. }
  3082. }
  3083. /**
  3084. * Get all the notification subscriptions of the user
  3085. * = which forums and which threads does the user wants to be informed of when a new
  3086. * post is added to this thread
  3087. *
  3088. * @param integer $user_id the user_id of a user (default = 0 => the current user)
  3089. * @param boolean $force force get the notification subscriptions (even if the information is already in the session
  3090. *
  3091. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  3092. * @version May 2008, dokeos 1.8.5
  3093. * @since May 2008, dokeos 1.8.5
  3094. */
  3095. function get_notifications_of_user($user_id = 0, $force = false) {
  3096. global $_course;
  3097. $course = api_get_course_id();
  3098. if (empty($course) OR $course==-1) {
  3099. return null;
  3100. }
  3101. if ($user_id == 0) {
  3102. global $_user;
  3103. $user_id = $_user['user_id'];
  3104. }
  3105. // database table definition
  3106. $table_notification = Database::get_course_table('forum_notification');
  3107. $my_code = isset($_course['code']) ? $_course['code'] : '';
  3108. if (!isset($_SESSION['forum_notification']) OR $_SESSION['forum_notification']['course'] <> $my_code OR $force=true) {
  3109. $_SESSION['forum_notification']['course'] = $my_code;
  3110. $sql = "SELECT * FROM $table_notification WHERE user_id='".Database::escape_string($user_id)."'";
  3111. $result=api_sql_query($sql, __FILE__, __LINE__);
  3112. while ($row=Database::fetch_array($result)) {
  3113. if (!is_null($row['forum_id'])) {
  3114. $_SESSION['forum_notification']['forum'][] = $row['forum_id'];
  3115. }
  3116. if (!is_null($row['thread_id'])) {
  3117. $_SESSION['forum_notification']['thread'][] = $row['thread_id'];
  3118. }
  3119. }
  3120. }
  3121. }
  3122. /**
  3123. * This function counts the number of post inside a thread
  3124. * @param int Thread ID
  3125. * @return int the number of post inside a thread
  3126. * @author Jhon Hinojosa <jhon.hinojosa@dokeos.com>,
  3127. * @version octubre 2008, dokeos 1.8
  3128. */
  3129. function count_number_of_post_in_thread($thread_id) {
  3130. global $table_posts;
  3131. $sql = "SELECT * FROM $table_posts WHERE thread_id='".Database::escape_string($thread_id)."' ";
  3132. $result = api_sql_query($sql, __FILE__, __LINE__);
  3133. return count(api_store_result($result));
  3134. }
  3135. /**
  3136. * This function counts the number of post inside a thread user
  3137. * @param int Thread ID
  3138. * @param int User ID
  3139. * @return int the number of post inside a thread user
  3140. * @author Jhon Hinojosa <jhon.hinojosa@dokeos.com>,
  3141. * @version octubre 2008, dokeos 1.8
  3142. */
  3143. function count_number_of_post_for_user_thread($thread_id, $user_id) {
  3144. global $table_posts;
  3145. $sql = "SELECT * FROM $table_posts WHERE thread_id='".Database::escape_string($thread_id)."'
  3146. AND poster_id = '".Database::escape_string($user_id)."' ";
  3147. $result = api_sql_query($sql, __FILE__, __LINE__);
  3148. return count(api_store_result($result));
  3149. }
  3150. /**
  3151. * This function counts the number of user register in course
  3152. * @param int Course ID
  3153. * @return int the number of user register in course
  3154. * @author Jhon Hinojosa <jhon.hinojosa@dokeos.com>,
  3155. * @version octubre 2008, dokeos 1.8
  3156. */
  3157. function count_number_of_user_in_course($course_id) {
  3158. $table_course_rel_user = Database::get_main_table("course_rel_user");
  3159. $sql = "SELECT * FROM $table_course_rel_user WHERE course_code ='".Database::escape_string($course_id)."' ";
  3160. $result = api_sql_query($sql, __FILE__, __LINE__);
  3161. return count(api_store_result($result));
  3162. }
  3163. /**
  3164. * This function retrieves information of statistical
  3165. * @param int Thread ID
  3166. * @param int User ID
  3167. * @param int Course ID
  3168. * @return array the information of statistical
  3169. * @author Jhon Hinojosa <jhon.hinojosa@dokeos.com>,
  3170. * @version octubre 2008, dokeos 1.8
  3171. */
  3172. function get_statistical_information($thread_id, $user_id, $course_id) {
  3173. $stadistic = array();
  3174. $stadistic['user_course'] = count_number_of_user_in_course($course_id);
  3175. $stadistic['post'] = count_number_of_post_in_thread($thread_id);
  3176. $stadistic['user_post'] = count_number_of_post_for_user_thread($thread_id, $user_id);
  3177. //$stadistic['average'] = get_average_of_thread_post_user();
  3178. return $stadistic;
  3179. }
  3180. /**
  3181. * This function counts the number of post inside a thread
  3182. * @param int Thread ID
  3183. * @param int User ID
  3184. * @return int the number of post inside a thread
  3185. * @author Jhon Hinojosa <jhon.hinojosa@dokeos.com>,
  3186. * @version octubre 2008, dokeos 1.8
  3187. */
  3188. function get_thread_user_post($thread_id, $user_id ) {
  3189. global $table_posts;
  3190. global $table_users;
  3191. $sql = "SELECT * FROM $table_posts posts
  3192. LEFT JOIN $table_users users
  3193. ON posts.poster_id=users.user_id
  3194. WHERE posts.thread_id='".Database::escape_string($thread_id)."'
  3195. AND posts.poster_id='".Database::escape_string($user_id)."'
  3196. ORDER BY posts.post_id ASC";
  3197. $result=api_sql_query($sql, __FILE__, __LINE__);
  3198. while ($row=Database::fetch_array($result)) {
  3199. $row['status'] = '1';
  3200. $post_list[]=$row;
  3201. $sql = "SELECT * FROM $table_posts posts
  3202. LEFT JOIN $table_users users
  3203. ON posts.poster_id=users.user_id
  3204. WHERE posts.thread_id='".Database::escape_string($thread_id)."'
  3205. AND posts.post_parent_id='".$row['post_id']."'
  3206. ORDER BY posts.post_id ASC";
  3207. $result2=api_sql_query($sql, __FILE__, __LINE__);
  3208. while ($row2=Database::fetch_array($result2))
  3209. {
  3210. $row2['status'] = '0';
  3211. $post_list[] = $row2;
  3212. }
  3213. }
  3214. return $post_list;
  3215. }
  3216. /* This function get the name of an user by id
  3217. * @param user_id int
  3218. * return String
  3219. * @author Christian Fasanando
  3220. */
  3221. function get_name_user_by_id($user_id) {
  3222. $t_users = Database :: get_main_table(TABLE_MAIN_USER);
  3223. $sql ="SELECT CONCAT(firstname,' ',lastname) FROM ".$t_users." WHERE user_id = '".$user_id."' ";
  3224. $result = api_sql_query($sql, __FILE__, __LINE__);
  3225. $row = Database::fetch_array($result);
  3226. return $row[0];
  3227. }
  3228. /* This function get the name of an thread by id
  3229. * @param thread_id int
  3230. * return String
  3231. * @author Christian Fasanando
  3232. */
  3233. function get_name_thread_by_id($thread_id) {
  3234. $t_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD,'');
  3235. $sql ="SELECT thread_title FROM ".$t_forum_thread." WHERE thread_id = '".$thread_id."' ";
  3236. $result = api_sql_query($sql, __FILE__, __LINE__);
  3237. $row = Database::fetch_array($result);
  3238. return $row[0];
  3239. }