forumfunction.inc.php 204 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * These files are a complete rework of the forum. The database structure is
  5. * based on phpBB but all the code is rewritten. A lot of new functionalities
  6. * are added:
  7. * - forum categories and forums can be sorted up or down, locked or made invisible
  8. * - consistent and integrated forum administration
  9. * - forum options: are students allowed to edit their post?
  10. * moderation of posts (approval)
  11. * reply only forums (students cannot create new threads)
  12. * multiple forums per group
  13. * - sticky messages
  14. * - new view option: nested view
  15. * - quoting a message
  16. *
  17. * @package chamilo.forum
  18. *
  19. * @todo several functions have to be moved to the itemmanager library
  20. * @todo displaying icons => display library
  21. * @todo complete the missing phpdoc the correct order should be
  22. */
  23. /**
  24. * code
  25. */
  26. use \ChamiloSession as Session;
  27. require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/gradebook_functions.inc.php';
  28. get_notifications_of_user();
  29. /* Javascript */
  30. $htmlHeadXtra[] = '<script type="text/javascript">
  31. function setFocus(){
  32. $("#forum_title").focus();
  33. $("#category_title").focus();
  34. $("#search_title").focus();
  35. }
  36. $(document).ready(function () {
  37. setFocus();
  38. });
  39. </script>';
  40. /**
  41. * This function handles all the forum and forumcategories actions. This is a wrapper for the
  42. * forum and forum categories. All this code code could go into the section where this function is
  43. * called but this make the code there cleaner.
  44. * @param int Learning path ID
  45. * @return void
  46. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  47. * @author Juan Carlos Raña Trabado (return to lp_id)
  48. * @version may 2011, Chamilo 1.8.8
  49. */
  50. function handle_forum_and_forumcategories($lp_id = null)
  51. {
  52. $action_forum_cat = isset($_GET['action']) ? $_GET['action'] : '';
  53. $post_submit_cat = isset($_POST['SubmitForumCategory']) ? true : false;
  54. $post_submit_forum = isset($_POST['SubmitForum']) ? true : false;
  55. $get_id = isset($_GET['id']) ? $_GET['id'] : '';
  56. // Adding a forum category
  57. if (($action_forum_cat == 'add' && $_GET['content'] == 'forumcategory') || $post_submit_cat) {
  58. show_add_forumcategory_form(array(), $lp_id); //$lp_id when is called from learning path
  59. }
  60. // Adding a forum
  61. if ((($action_forum_cat == 'add' || $action_forum_cat == 'edit') && $_GET['content'] == 'forum') || $post_submit_forum) {
  62. if ($action_forum_cat == 'edit' && $get_id || $post_submit_forum) {
  63. $inputvalues = get_forums(intval($get_id)); // Note: This has to be cleaned first.
  64. } else {
  65. $inputvalues = array();
  66. }
  67. show_add_forum_form($inputvalues, $lp_id);
  68. }
  69. // Edit a forum category
  70. if (($action_forum_cat == 'edit' && $_GET['content'] == 'forumcategory' && isset($_GET['id'])) || (isset($_POST['SubmitEditForumCategory'])) ? true : false) {
  71. $forum_category = get_forum_categories(strval(intval($_GET['id']))); // Note: This has to be cleaned first.
  72. show_edit_forumcategory_form($forum_category);
  73. }
  74. // Delete a forum category
  75. if ((isset($_GET['action']) && $_GET['action'] == 'delete') && isset($_GET['content']) && $get_id) {
  76. $id_forum = intval($get_id);
  77. $list_threads = get_threads($id_forum);
  78. for ($i = 0; $i < count($list_threads); $i++) {
  79. delete_forum_forumcategory_thread('thread', $list_threads[$i]['thread_id']);
  80. require_once api_get_path(SYS_CODE_PATH).'gradebook/lib/gradebook_functions.inc.php';
  81. $link_info = is_resource_in_course_gradebook(
  82. api_get_course_id(),
  83. 5,
  84. intval($list_threads[$i]['thread_id']),
  85. api_get_session_id()
  86. );
  87. if ($link_info !== false) {
  88. remove_resource_from_course_gradebook($link_info['id']);
  89. }
  90. }
  91. $return_message = delete_forum_forumcategory_thread($_GET['content'], $_GET['id']);
  92. Display::display_confirmation_message($return_message, false);
  93. }
  94. // Change visibility of a forum or a forum category.
  95. if (($action_forum_cat == 'invisible' || $action_forum_cat == 'visible') && isset($_GET['content']) && isset($_GET['id'])) {
  96. $return_message = change_visibility(
  97. $_GET['content'],
  98. $_GET['id'],
  99. $_GET['action']
  100. ); // Note: This has to be cleaned first.
  101. Display::display_confirmation_message($return_message, false);
  102. }
  103. // Change lock status of a forum or a forum category.
  104. if (($action_forum_cat == 'lock' || $action_forum_cat == 'unlock') && isset($_GET['content']) && isset($_GET['id'])) {
  105. $return_message = change_lock_status(
  106. $_GET['content'],
  107. $_GET['id'],
  108. $_GET['action']
  109. ); // Note: This has to be cleaned first.
  110. Display::display_confirmation_message($return_message, false);
  111. }
  112. // Move a forum or a forum category.
  113. if ($action_forum_cat == 'move' && isset($_GET['content']) && isset($_GET['id']) && isset($_GET['direction'])) {
  114. $return_message = move_up_down(
  115. $_GET['content'],
  116. $_GET['direction'],
  117. $_GET['id']
  118. ); // Note: This has to be cleaned first.
  119. Display::display_confirmation_message($return_message, false);
  120. }
  121. }
  122. /**
  123. * This function displays the form that is used to add a forum category.
  124. *
  125. * @param array input values (deprecated, set to null when calling)
  126. * @param int Learning path ID
  127. * @return void HTML
  128. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  129. * @author Juan Carlos Raña Trabado (return to lp_id)
  130. * @version may 2011, Chamilo 1.8.8
  131. */
  132. function show_add_forumcategory_form($inputvalues = array(), $lp_id)
  133. {
  134. $gradebook = Security::remove_XSS($_GET['gradebook']);
  135. // Initialize the object.
  136. $form = new FormValidator('forumcategory', 'post', 'index.php?gradebook='.$gradebook.'&'.api_get_cidreq());
  137. // hidden field if from learning path
  138. $form->addElement('hidden', 'lp_id', $lp_id);
  139. // Settting the form elements.
  140. $form->addElement('header', '', get_lang('AddForumCategory'));
  141. $form->addElement('text', 'forum_category_title', get_lang('Title'), 'class="input_titles" id="category_title"');
  142. //$form->applyFilter('forum_category_title', 'html_filter');
  143. $form->addElement(
  144. 'html_editor',
  145. 'forum_category_comment',
  146. get_lang('Description'),
  147. null,
  148. array('ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200')
  149. );
  150. //$form->applyFilter('forum_category_comment', 'html_filter');
  151. $form->addElement('style_submit_button', 'SubmitForumCategory', get_lang('CreateCategory'), 'class="add"');
  152. // Setting the rules.
  153. $form->addRule('forum_category_title', get_lang('ThisFieldIsRequired'), 'required');
  154. // The validation or display
  155. if ($form->validate()) {
  156. $check = Security::check_token('post');
  157. if ($check) {
  158. $values = $form->exportValues();
  159. store_forumcategory($values);
  160. }
  161. Security::clear_token();
  162. } else {
  163. $token = Security::get_token();
  164. $form->addElement('hidden', 'sec_token');
  165. $form->setConstants(array('sec_token' => $token));
  166. $form->display();
  167. }
  168. }
  169. /**
  170. * This function displays the form that is used to add a forum category.
  171. *
  172. * @param array
  173. * @return void HTML
  174. *
  175. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  176. *
  177. * Juan Carlos Raña Trabado (return to lp_id)
  178. *
  179. * @version may 2011, Chamilo 1.8.8
  180. */
  181. function show_add_forum_form($inputvalues = array(), $lp_id)
  182. {
  183. $_course = api_get_course_info();
  184. $gradebook = Security::remove_XSS($_GET['gradebook']);
  185. // Initialize the object.
  186. $form = new FormValidator('forumcategory', 'post', 'index.php?gradebook='.$gradebook.'&'.api_get_cidreq());
  187. // The header for the form
  188. if (!empty($inputvalues)) {
  189. $form_title = get_lang('EditForum');
  190. } else {
  191. $form_title = get_lang('AddForum');
  192. }
  193. $session_header = isset($_SESSION['session_name']) ? ' ('.$_SESSION['session_name'].') ' : '';
  194. $form->addElement('header', $form_title.$session_header);
  195. // We have a hidden field if we are editing.
  196. if (!empty($inputvalues) && is_array($inputvalues)) {
  197. $my_forum_id = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
  198. $form->addElement('hidden', 'forum_id', $my_forum_id);
  199. }
  200. $lp_id = intval($lp_id);
  201. // hidden field if from learning path
  202. $form->addElement('hidden', 'lp_id', $lp_id);
  203. // The title of the forum
  204. $form->addElement('text', 'forum_title', get_lang('Title'), 'class="input_titles" id="forum_title"');
  205. // The comment of the forum.
  206. $form->addElement(
  207. 'html_editor',
  208. 'forum_comment',
  209. get_lang('Description'),
  210. null,
  211. array('ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200')
  212. );
  213. // Dropdown list: Forum categories
  214. $forum_categories = get_forum_categories();
  215. foreach ($forum_categories as $key => $value) {
  216. $forum_categories_titles[$value['cat_id']] = $value['cat_title'];
  217. }
  218. $form->addElement('select', 'forum_category', get_lang('InForumCategory'), $forum_categories_titles);
  219. $form->applyFilter('forum_category', 'html_filter');
  220. if ($_course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD) {
  221. // This is for horizontal
  222. $group = array();
  223. $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('Yes'), 1);
  224. $group[] = $form->createElement('radio', 'allow_anonymous', null, get_lang('No'), 0);
  225. $form->addGroup($group, 'allow_anonymous_group', get_lang('AllowAnonymousPosts'), '&nbsp;');
  226. }
  227. $form->addElement(
  228. 'advanced_settings',
  229. '<a href="javascript://" onclick="advanced_parameters()" ><span id="plus_minus">&nbsp;'.Display::return_icon(
  230. 'div_show.gif',
  231. get_lang('Show'),
  232. array('style' => 'vertical-align:middle')
  233. ).'&nbsp;'.get_lang('AdvancedParameters').'</span></a>',
  234. ''
  235. );
  236. $form->addElement('html', '<div id="options" style="display:none">');
  237. $group = array();
  238. $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('Yes'), 1);
  239. $group[] = $form->createElement('radio', 'students_can_edit', null, get_lang('No'), 0);
  240. $form->addGroup($group, 'students_can_edit_group', get_lang('StudentsCanEdit'), '&nbsp;');
  241. $group = array();
  242. $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Approval'), 1);
  243. $group[] = $form->createElement('radio', 'approval_direct', null, get_lang('Direct'), 0);
  244. $group = array();
  245. $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('Yes'), 1);
  246. $group[] = $form->createElement('radio', 'allow_attachments', null, get_lang('No'), 0);
  247. $group = array();
  248. $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('Yes'), 1);
  249. $group[] = $form->createElement('radio', 'allow_new_threads', null, get_lang('No'), 0);
  250. $form->addGroup($group, 'allow_new_threads_group', get_lang('AllowNewThreads'), '&nbsp;');
  251. $group = array();
  252. $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Flat'), 'flat');
  253. $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Threaded'), 'threaded');
  254. $group[] = $form->createElement('radio', 'default_view_type', null, get_lang('Nested'), 'nested');
  255. $form->addGroup($group, 'default_view_type_group', get_lang('DefaultViewType'), '&nbsp;');
  256. // Dropdown list: Groups
  257. $groups = GroupManager::get_group_list();
  258. $groups_titles[0] = get_lang('NotAGroupForum');
  259. foreach ($groups as $key => $value) {
  260. $groups_titles[$value['id']] = $value['name'];
  261. }
  262. $form->addElement('select', 'group_forum', get_lang('ForGroup'), $groups_titles);
  263. // Public or private group forum
  264. $group = array();
  265. $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Public'), 'public');
  266. $group[] = $form->createElement('radio', 'public_private_group_forum', null, get_lang('Private'), 'private');
  267. $form->addGroup($group, 'public_private_group_forum_group', get_lang('PublicPrivateGroupForum'), '&nbsp;');
  268. // Forum image
  269. $form->add_progress_bar();
  270. if (isset($inputvalues['forum_image']) && strlen($inputvalues['forum_image']) > 0) {
  271. $image_path = api_get_path(WEB_COURSE_PATH).api_get_course_path(
  272. ).'/upload/forum/images/'.$inputvalues['forum_image'];
  273. $image_size = api_getimagesize($image_path);
  274. $img_attributes = '';
  275. if (!empty($image_size)) {
  276. if ($image_size['width'] > 100 || $image_size['height'] > 100) {
  277. //limit display width and height to 100px
  278. $img_attributes = 'width="100" height="100"';
  279. }
  280. $show_preview_image = '<img src="'.$image_path.'" '.$img_attributes.'>';
  281. $form->addElement('label', get_lang('PreviewImage'), $show_preview_image);
  282. $form->addElement('checkbox', 'remove_picture', null, get_lang('DelImage'));
  283. }
  284. }
  285. $forum_image = isset($inputvalues['forum_image']) ? $inputvalues['forum_image'] : '';
  286. $form->addElement('file', 'picture', ($forum_image != '' ? get_lang('UpdateImage') : get_lang('AddImage')));
  287. $form->addRule('picture', get_lang('OnlyImagesAllowed'), 'filetype', array('jpg', 'jpeg', 'png', 'gif'));
  288. $form->addElement('html', '</div>');
  289. // The OK button
  290. if (isset($_GET['id']) && $_GET['action'] == 'edit') {
  291. $class = 'save';
  292. $text = get_lang('ModifyForum');
  293. } else {
  294. $class = 'add';
  295. $text = get_lang('CreateForum');
  296. }
  297. $form->addElement('style_submit_button', 'SubmitForum', $text, 'class="'.$class.'"');
  298. // setting the rules
  299. $form->addRule('forum_title', get_lang('ThisFieldIsRequired'), 'required');
  300. $form->addRule('forum_category', get_lang('ThisFieldIsRequired'), 'required');
  301. // Settings the defaults
  302. if (empty($inputvalues) || !is_array($inputvalues)) {
  303. $defaults['allow_anonymous_group']['allow_anonymous'] = 0;
  304. $defaults['students_can_edit_group']['students_can_edit'] = 0;
  305. $defaults['approval_direct_group']['approval_direct'] = 0;
  306. $defaults['allow_attachments_group']['allow_attachments'] = 1;
  307. $defaults['allow_new_threads_group']['allow_new_threads'] = 0;
  308. $defaults['default_view_type_group']['default_view_type'] = api_get_setting('default_forum_view');
  309. $defaults['public_private_group_forum_group']['public_private_group_forum'] = 'public';
  310. if (isset($_GET['forumcategory'])) {
  311. $defaults['forum_category'] = Security::remove_XSS($_GET['forumcategory']);
  312. }
  313. } else { // the default values when editing = the data in the table
  314. $defaults['forum_id'] = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
  315. $defaults['forum_title'] = prepare4display(
  316. isset($inputvalues['forum_title']) ? $inputvalues['forum_title'] : null
  317. );
  318. $defaults['forum_comment'] = prepare4display(
  319. isset($inputvalues['forum_comment']) ? $inputvalues['forum_comment'] : null
  320. );
  321. $defaults['forum_category'] = isset($inputvalues['forum_category']) ? $inputvalues['forum_category'] : null;
  322. $defaults['allow_anonymous_group']['allow_anonymous'] = isset($inputvalues['allow_anonymous']) ? $inputvalues['allow_anonymous'] : null;
  323. $defaults['students_can_edit_group']['students_can_edit'] = isset($inputvalues['allow_edit']) ? $inputvalues['allow_edit'] : null;
  324. $defaults['approval_direct_group']['approval_direct'] = isset($inputvalues['approval_direct_post']) ? $inputvalues['approval_direct_post'] : null;
  325. $defaults['allow_attachments_group']['allow_attachments'] = isset($inputvalues['allow_attachments']) ? $inputvalues['allow_attachments'] : null;
  326. $defaults['allow_new_threads_group']['allow_new_threads'] = isset($inputvalues['allow_new_threads']) ? $inputvalues['allow_new_threads'] : null;
  327. $defaults['default_view_type_group']['default_view_type'] = isset($inputvalues['default_view']) ? $inputvalues['default_view'] : null;
  328. $defaults['public_private_group_forum_group']['public_private_group_forum'] = isset($inputvalues['forum_group_public_private']) ? $inputvalues['forum_group_public_private'] : null;
  329. $defaults['group_forum'] = isset($inputvalues['forum_of_group']) ? $inputvalues['forum_of_group'] : null;
  330. }
  331. $form->setDefaults($defaults);
  332. // Validation or display
  333. if ($form->validate()) {
  334. $check = Security::check_token('post');
  335. if ($check) {
  336. $values = $form->exportValues();
  337. $return_message = store_forum($values);
  338. Display :: display_confirmation_message($return_message);
  339. }
  340. Security::clear_token();
  341. } else {
  342. $token = Security::get_token();
  343. $form->addElement('hidden', 'sec_token');
  344. $form->setConstants(array('sec_token' => $token));
  345. $form->display();
  346. }
  347. }
  348. /**
  349. * This function deletes the forum image if exists
  350. *
  351. * @param int forum id
  352. * @return boolean true if success
  353. * @author Julio Montoya <gugli100@gmail.com>
  354. * @version february 2006, dokeos 1.8
  355. */
  356. function delete_forum_image($forum_id)
  357. {
  358. $table_forums = Database::get_course_table(TABLE_FORUM);
  359. $course_id = api_get_course_int_id();
  360. $forum_id = Database::escape_string($forum_id);
  361. $sql = "SELECT forum_image FROM $table_forums WHERE forum_id = '".$forum_id."' AND c_id = $course_id";
  362. $result = Database::query($sql);
  363. $row = Database::fetch_array($result);
  364. if ($row['forum_image'] != '') {
  365. $del_file = api_get_path(SYS_COURSE_PATH).api_get_course_path().'/upload/forum/images/'.$row['forum_image'];
  366. return @unlink($del_file);
  367. } else {
  368. return false;
  369. }
  370. }
  371. /**
  372. * This function displays the form that is used to edit a forum category.
  373. * This is more or less a copy from the show_add_forumcategory_form function with the only difference that is uses
  374. * some default values. I tried to have both in one function but this gave problems with the handle_forum_and_forumcategories function
  375. * (storing was done twice)
  376. *
  377. * @param array
  378. * @return void HTML
  379. *
  380. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  381. * @version february 2006, dokeos 1.8
  382. */
  383. function show_edit_forumcategory_form($inputvalues = array())
  384. {
  385. // Initialize the object.
  386. $gradebook = Security::remove_XSS($_GET['gradebook']);
  387. $form = new FormValidator('forumcategory', 'post', 'index.php?&amp;gradebook='.$gradebook.'');
  388. // Settting the form elements.
  389. $form->addElement('header', '', get_lang('EditForumCategory'));
  390. $form->addElement('hidden', 'forum_category_id');
  391. $form->addElement('text', 'forum_category_title', get_lang('Title'), 'class="input_titles"');
  392. //$form->applyFilter('forum_category_title', 'html_filter');
  393. $form->addElement(
  394. 'html_editor',
  395. 'forum_category_comment',
  396. get_lang('Comment'),
  397. null,
  398. array('ToolbarSet' => 'Forum', 'Width' => '98%', 'Height' => '200')
  399. );
  400. //$form->applyFilter('forum_category_comment', 'html_filter');
  401. $form->addElement('style_submit_button', 'SubmitEditForumCategory', get_lang('ModifyCategory'), 'class="save"');
  402. // Setting the default values.
  403. $defaultvalues['forum_category_id'] = $inputvalues['cat_id'];
  404. $defaultvalues['forum_category_title'] = $inputvalues['cat_title'];
  405. $defaultvalues['forum_category_comment'] = $inputvalues['cat_comment'];
  406. $form->setDefaults($defaultvalues);
  407. // Setting the rules.
  408. $form->addRule('forum_category_title', get_lang('ThisFieldIsRequired'), 'required');
  409. // Validation or display
  410. if ($form->validate()) {
  411. $check = Security::check_token('post');
  412. if ($check) {
  413. $values = $form->exportValues();
  414. store_forumcategory($values);
  415. }
  416. Security::clear_token();
  417. } else {
  418. $token = Security::get_token();
  419. $form->addElement('hidden', 'sec_token');
  420. $form->setConstants(array('sec_token' => $token));
  421. $form->display();
  422. }
  423. }
  424. /**
  425. * This function stores the forum category in the database. The new category is added to the end.
  426. *
  427. * @param array
  428. * @return void HMTL language variable
  429. *
  430. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  431. * @version february 2006, dokeos 1.8
  432. */
  433. function store_forumcategory($values)
  434. {
  435. $_course = api_get_course_info();
  436. $course_id = api_get_course_int_id();
  437. $table_categories = Database::get_course_table(TABLE_FORUM_CATEGORY);
  438. // Find the max cat_order. The new forum category is added at the end => max cat_order + &
  439. $sql = "SELECT MAX(cat_order) as sort_max FROM $table_categories WHERE c_id = $course_id";
  440. $result = Database::query($sql);
  441. $row = Database::fetch_array($result);
  442. $new_max = $row['sort_max'] + 1;
  443. $session_id = api_get_session_id();
  444. $clean_cat_title = Database::escape_string($values['forum_category_title']);
  445. if (isset($values['forum_category_id'])) { // Storing after edition.
  446. $sql = "UPDATE ".$table_categories." SET cat_title='".$clean_cat_title."', cat_comment='".Database::escape_string(
  447. $values['forum_category_comment']
  448. )."'
  449. WHERE c_id = $course_id AND cat_id='".Database::escape_string($values['forum_category_id'])."'";
  450. Database::query($sql);
  451. $last_id = Database::insert_id();
  452. api_item_property_update(
  453. api_get_course_info(),
  454. TOOL_FORUM_CATEGORY,
  455. $values['forum_category_id'],
  456. 'ForumCategoryUpdated',
  457. api_get_user_id()
  458. );
  459. $return_message = get_lang('ForumCategoryEdited');
  460. } else {
  461. $sql = "INSERT INTO ".$table_categories." (c_id, cat_title, cat_comment, cat_order, session_id)
  462. VALUES (".$course_id.", '".$clean_cat_title."','".Database::escape_string(
  463. $values['forum_category_comment']
  464. )."','".Database::escape_string($new_max)."','".Database::escape_string($session_id)."')";
  465. Database::query($sql);
  466. $last_id = Database::insert_id();
  467. if ($last_id > 0) {
  468. api_item_property_update(
  469. api_get_course_info(),
  470. TOOL_FORUM_CATEGORY,
  471. $last_id,
  472. 'ForumCategoryAdded',
  473. api_get_user_id()
  474. );
  475. api_set_default_visibility($_course, $last_id, TOOL_FORUM_CATEGORY);
  476. }
  477. $return_message = get_lang('ForumCategoryAdded');
  478. }
  479. Display :: display_confirmation_message($return_message);
  480. }
  481. /**
  482. * This function stores the forum in the database. The new forum is added to the end.
  483. *
  484. * @param array
  485. * @return string language variable
  486. *
  487. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  488. * @version february 2006, dokeos 1.8
  489. */
  490. function store_forum($values)
  491. {
  492. $_course = api_get_course_info();
  493. $course_id = api_get_course_int_id();
  494. $session_id = api_get_session_id();
  495. if (isset($values['group_id']) && !empty($values['group_id'])) {
  496. $group_id = $values['group_id'];
  497. } else {
  498. $group_id = api_get_group_id();
  499. }
  500. $table_forums = Database::get_course_table(TABLE_FORUM);
  501. // Find the max forum_order for the given category. The new forum is added at the end => max cat_order + &
  502. if (is_null($values['forum_category'])) {
  503. $new_max = null;
  504. } else {
  505. $sql = "SELECT MAX(forum_order) as sort_max
  506. FROM ".$table_forums."
  507. WHERE c_id = $course_id AND
  508. forum_category='".Database::escape_string($values['forum_category'])."'";
  509. $result = Database::query($sql);
  510. $row = Database::fetch_array($result);
  511. $new_max = $row['sort_max'] + 1;
  512. }
  513. $clean_title = Database::escape_string($values['forum_title']);
  514. // Forum images
  515. $image_moved = false;
  516. if (!empty($_FILES['picture']['name'])) {
  517. $upload_ok = FileManager::process_uploaded_file($_FILES['picture']);
  518. $has_attachment = true;
  519. } else {
  520. $image_moved = true;
  521. }
  522. // Remove existing picture if it was requested.
  523. if (!empty($_POST['remove_picture'])) {
  524. delete_forum_image($values['forum_id']);
  525. }
  526. if (isset($upload_ok)) {
  527. if ($has_attachment) {
  528. $course_dir = $_course['path'].'/upload/forum/images';
  529. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  530. $updir = $sys_course_path.$course_dir;
  531. // Try to add an extension to the file if it hasn't one.
  532. $new_file_name = FileManager::add_ext_on_mime(
  533. Database::escape_string($_FILES['picture']['name']),
  534. $_FILES['picture']['type']
  535. );
  536. // User's file name
  537. $file_name = $_FILES['picture']['name'];
  538. if (!FileManager::filter_extension($new_file_name)) {
  539. //Display :: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
  540. $image_moved = false;
  541. } else {
  542. $file_extension = explode('.', $_FILES['picture']['name']);
  543. $file_extension = strtolower($file_extension[sizeof($file_extension) - 1]);
  544. $new_file_name = uniqid('').'.'.$file_extension;
  545. $new_path = $updir.'/'.$new_file_name;
  546. $result = @move_uploaded_file($_FILES['picture']['tmp_name'], $new_path);
  547. // Storing the attachments if any
  548. if ($result) {
  549. $image_moved = true;
  550. }
  551. }
  552. }
  553. }
  554. if (isset($values['forum_id'])) {
  555. $sql_image = isset($sql_image) ? $sql_image : '';
  556. $new_file_name = isset($new_file_name) ? $new_file_name : '';
  557. if ($image_moved) {
  558. if (empty($_FILES['picture']['name'])) {
  559. $sql_image = " ";
  560. } else {
  561. $sql_image = " forum_image='".Database::escape_string($new_file_name)."', ";
  562. delete_forum_image($values['forum_id']);
  563. }
  564. }
  565. // Storing after edition.
  566. $sql = "UPDATE ".$table_forums." SET
  567. forum_title='".$clean_title."',
  568. ".$sql_image."
  569. forum_comment='".Database::escape_string(stripslashes($values['forum_comment']))."',
  570. forum_category='".Database::escape_string(stripslashes($values['forum_category']))."',
  571. allow_anonymous='".Database::escape_string(
  572. isset($values['allow_anonymous_group']['allow_anonymous']) ? $values['allow_anonymous_group']['allow_anonymous'] : null
  573. )."',
  574. allow_edit='".Database::escape_string($values['students_can_edit_group']['students_can_edit'])."',
  575. approval_direct_post='".Database::escape_string(
  576. isset($values['approval_direct_group']['approval_direct']) ? $values['approval_direct_group']['approval_direct'] : null
  577. )."',
  578. allow_attachments='".Database::escape_string(
  579. isset($values['allow_attachments_group']['allow_attachments']) ? $values['allow_attachments_group']['allow_attachments'] : null
  580. )."',
  581. allow_new_threads='".Database::escape_string($values['allow_new_threads_group']['allow_new_threads'])."',
  582. forum_group_public_private='".Database::escape_string(
  583. $values['public_private_group_forum_group']['public_private_group_forum']
  584. )."',
  585. default_view='".Database::escape_string($values['default_view_type_group']['default_view_type'])."',
  586. forum_of_group='".Database::escape_string($values['group_forum'])."'
  587. WHERE c_id = $course_id AND forum_id='".Database::escape_string($values['forum_id'])."'";
  588. Database::query($sql);
  589. api_item_property_update(
  590. $_course,
  591. TOOL_FORUM,
  592. Database::escape_string($values['forum_id']),
  593. 'ForumUpdated',
  594. api_get_user_id(),
  595. $group_id
  596. );
  597. $return_message = get_lang('ForumEdited');
  598. } else {
  599. $sql_image = '';
  600. if ($image_moved) {
  601. $new_file_name = isset($new_file_name) ? $new_file_name : '';
  602. $sql_image = "'".$new_file_name."', ";
  603. }
  604. $b = isset($values['forum_comment']) ? $values['forum_comment'] : null;
  605. $sql = "INSERT INTO ".$table_forums." (c_id, 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)
  606. VALUES (
  607. ".$course_id.",
  608. '".$clean_title."',
  609. ".$sql_image."
  610. '".Database::escape_string(isset($values['forum_comment']) ? $values['forum_comment'] : null)."',
  611. '".Database::escape_string(isset($values['forum_category']) ? $values['forum_category'] : null)."',
  612. '".Database::escape_string(
  613. isset($values['allow_anonymous_group']['allow_anonymous']) ? $values['allow_anonymous_group']['allow_anonymous'] : null
  614. )."',
  615. '".Database::escape_string(
  616. isset($values['students_can_edit_group']['students_can_edit']) ? $values['students_can_edit_group']['students_can_edit'] : null
  617. )."',
  618. '".Database::escape_string(
  619. isset($values['approval_direct_group']['approval_direct']) ? $values['approval_direct_group']['approval_direct'] : null
  620. )."',
  621. '".Database::escape_string(
  622. isset($values['allow_attachments_group']['allow_attachments']) ? $values['allow_attachments_group']['allow_attachments'] : null
  623. )."',
  624. '".Database::escape_string(
  625. isset($values['allow_new_threads_group']['allow_new_threads']) ? $values['allow_new_threads_group']['allow_new_threads'] : null
  626. )."',
  627. '".Database::escape_string(
  628. isset($values['default_view_type_group']['default_view_type']) ? $values['default_view_type_group']['default_view_type'] : null
  629. )."',
  630. '".Database::escape_string(isset($values['group_forum']) ? $values['group_forum'] : null)."',
  631. '".Database::escape_string(
  632. isset($values['public_private_group_forum_group']['public_private_group_forum']) ? $values['public_private_group_forum_group']['public_private_group_forum'] : null
  633. )."',
  634. '".Database::escape_string(isset($new_max) ? $new_max : null)."',
  635. ".intval($session_id).")";
  636. Database::query($sql);
  637. $last_id = Database::insert_id();
  638. if ($last_id > 0) {
  639. api_item_property_update($_course, TOOL_FORUM, $last_id, 'ForumAdded', api_get_user_id(), $group_id);
  640. api_set_default_visibility($_course, $last_id, TOOL_FORUM, $group_id);
  641. }
  642. $return_message = get_lang('ForumAdded');
  643. }
  644. return $return_message;
  645. }
  646. /**
  647. * This function deletes a forum or a forum category
  648. * This function currently does not delete the forums inside the category, nor the threads and replies inside these forums.
  649. * For the moment this is the easiest method and it has the advantage that it allows to recover fora that were acidently deleted
  650. * when the forum category got deleted.
  651. *
  652. * @param $content = what we are deleting (a forum or a forum category)
  653. * @param $id The id of the forum category that has to be deleted.
  654. *
  655. * @todo write the code for the cascading deletion of the forums inside a forum category and also the threads and replies inside these forums
  656. * @todo config setting for recovery or not (see also the documents tool: real delete or not).
  657. * @return void
  658. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  659. * @version february 2006, dokeos 1.8
  660. */
  661. function delete_forum_forumcategory_thread($content, $id)
  662. {
  663. $_course = api_get_course_info();
  664. $table_forums = Database::get_course_table(TABLE_FORUM);
  665. $table_forums_post = Database::get_course_table(TABLE_FORUM_POST);
  666. $table_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
  667. $course_id = api_get_course_int_id();
  668. // Delete all attachment file about this tread id.
  669. $sql = "SELECT post_id FROM $table_forums_post WHERE c_id = $course_id AND thread_id = '".(int)$id."' ";
  670. $res = Database::query($sql);
  671. while ($poster_id = Database::fetch_row($res)) {
  672. delete_attachment($poster_id[0]);
  673. }
  674. if ($content == 'forumcategory') {
  675. $tool_constant = TOOL_FORUM_CATEGORY;
  676. $return_message = get_lang('ForumCategoryDeleted');
  677. if (!empty($forum_list)) {
  678. $sql = "SELECT forum_id FROM ".$table_forums."WHERE c_id = $course_id AND forum_category='".$id."'";
  679. $result = Database::query($sql);
  680. $row = Database::fetch_array($result);
  681. foreach ($row as $arr_forum) {
  682. $forum_id = $arr_forum['forum_id'];
  683. api_item_property_update($_course, 'forum', $forum_id, 'delete', api_get_user_id());
  684. }
  685. }
  686. }
  687. if ($content == 'forum') {
  688. $tool_constant = TOOL_FORUM;
  689. $return_message = get_lang('ForumDeleted');
  690. if (!empty($number_threads)) {
  691. $sql = "SELECT thread_id FROM".$table_forum_thread."WHERE c_id = $course_id AND forum_id='".$id."'";
  692. $result = Database::query($sql);
  693. $row = Database::fetch_array($result);
  694. foreach ($row as $arr_forum) {
  695. $forum_id = $arr_forum['thread_id'];
  696. api_item_property_update($_course, 'forum_thread', $forum_id, 'delete', api_get_user_id());
  697. }
  698. }
  699. }
  700. if ($content == 'thread') {
  701. $tool_constant = TOOL_FORUM_THREAD;
  702. $return_message = get_lang('ThreadDeleted');
  703. }
  704. api_item_property_update(
  705. $_course,
  706. $tool_constant,
  707. $id,
  708. 'delete',
  709. api_get_user_id()
  710. ); // Note: Check if this returns a true and if so => return $return_message, if not => return false;
  711. return $return_message;
  712. }
  713. /**
  714. * This function deletes a forum post. This separate function is needed because forum posts do not appear in the item_property table (yet)
  715. * and because deleting a post also has consequence on the posts that have this post as parent_id (they are also deleted).
  716. * an alternative would be to store the posts also in item_property and mark this post as deleted (visibility = 2).
  717. * We also have to decrease the number of replies in the thread table
  718. *
  719. * @param $post_id the id of the post that will be deleted
  720. * @todo write recursive function that deletes all the posts that have this message as parent
  721. * @return string language variable
  722. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  723. * @author Hubert Borderiou Function cleanead and fixed
  724. * @version february 2006
  725. */
  726. function delete_post($post_id)
  727. {
  728. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  729. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  730. $post_id = intval($post_id);
  731. $course_id = api_get_course_int_id();
  732. // Get parent_post_id of deleted post.
  733. $tab_post_info = get_post_information($post_id);
  734. if ($tab_post_info) {
  735. $post_parent_id_of_deleted_post = $tab_post_info['post_parent_id'];
  736. $thread_id_of_deleted_post = $tab_post_info['thread_id'];
  737. $forum_if_of_deleted_post = $tab_post_info['forum_id'];
  738. $sql = "UPDATE $table_posts SET post_parent_id=$post_parent_id_of_deleted_post
  739. WHERE c_id = $course_id AND post_parent_id=$post_id AND thread_id=$thread_id_of_deleted_post AND forum_id=$forum_if_of_deleted_post;";
  740. Database::query($sql);
  741. $sql = "DELETE FROM $table_posts WHERE c_id = $course_id AND post_id='".Database::escape_string(
  742. $post_id
  743. )."'"; // Note: This has to be a recursive function that deletes all of the posts in this block.
  744. Database::query($sql);
  745. // Delete attachment file about this post id.
  746. delete_attachment($post_id);
  747. }
  748. $last_post_of_thread = check_if_last_post_of_thread($_GET['thread']);
  749. if (is_array($last_post_of_thread)) {
  750. // Decreasing the number of replies for this thread and also changing the last post information.
  751. $sql = "UPDATE $table_threads SET thread_replies=thread_replies-1,
  752. thread_last_post='".Database::escape_string($last_post_of_thread['post_id'])."',
  753. thread_date='".Database::escape_string($last_post_of_thread['post_date'])."'
  754. WHERE c_id = $course_id AND thread_id='".intval($_GET['thread'])."'";
  755. Database::query($sql);
  756. return 'PostDeleted';
  757. }
  758. if (!$last_post_of_thread) {
  759. // We deleted the very single post of the thread so we need to delete the entry in the thread table also.
  760. $sql = "DELETE FROM $table_threads WHERE c_id = $course_id AND thread_id='".intval($_GET['thread'])."'";
  761. Database::query($sql);
  762. return 'PostDeletedSpecial';
  763. }
  764. }
  765. /**
  766. * This function gets the all information of the last (=most recent) post of the thread
  767. * This can be done by sorting the posts that have the field thread_id=$thread_id and sort them by post_date
  768. *
  769. * @param $thread_id the id of the thread we want to know the last post of.
  770. * @return an array or bool if there is a last post found, false if there is no post entry linked to that thread => thread will be deleted
  771. *
  772. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  773. * @version february 2006, dokeos 1.8
  774. */
  775. function check_if_last_post_of_thread($thread_id)
  776. {
  777. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  778. $course_id = api_get_course_int_id();
  779. $sql = "SELECT * FROM $table_posts WHERE c_id = $course_id AND thread_id='".Database::escape_string(
  780. $thread_id
  781. )."' ORDER BY post_date DESC";
  782. $result = Database::query($sql);
  783. if (Database::num_rows($result) > 0) {
  784. $row = Database::fetch_array($result);
  785. return $row;
  786. } else {
  787. return false;
  788. }
  789. }
  790. /**
  791. * This function takes care of the display of the visibility icon
  792. *
  793. * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  794. * @param $id the id of the content we want to make invisible
  795. * @param $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
  796. * @return void string HTML
  797. *
  798. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  799. * @version february 2006, dokeos 1.8
  800. */
  801. function display_visible_invisible_icon($content, $id, $current_visibility_status, $additional_url_parameters = '')
  802. {
  803. global $origin;
  804. $gradebook = Security::remove_XSS($_GET['gradebook']);
  805. $id = Security::remove_XSS($id);
  806. if ($current_visibility_status == '1') {
  807. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&amp;gidReq='.api_get_group_id().'&amp;';
  808. if (is_array($additional_url_parameters)) {
  809. foreach ($additional_url_parameters as $key => $value) {
  810. echo $key.'='.$value.'&amp;';
  811. }
  812. }
  813. echo 'action=invisible&amp;content='.$content.'&amp;id='.$id.'&gradebook='.$gradebook.'&amp;origin='.$origin.'">'.Display::return_icon(
  814. 'visible.png',
  815. get_lang('MakeInvisible'),
  816. array(),
  817. ICON_SIZE_SMALL
  818. ).'</a>';
  819. }
  820. if ($current_visibility_status == '0') {
  821. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&amp;';
  822. if (is_array($additional_url_parameters)) {
  823. foreach ($additional_url_parameters as $key => $value) {
  824. echo $key.'='.$value.'&amp;';
  825. }
  826. }
  827. echo 'action=visible&amp;content='.$content.'&amp;id='.$id.'&gradebook='.$gradebook.'&amp;origin='.$origin.'">'.Display::return_icon(
  828. 'invisible.png',
  829. get_lang('MakeVisible'),
  830. array(),
  831. ICON_SIZE_SMALL
  832. ).'</a>';
  833. }
  834. }
  835. /**
  836. * This function takes care of the display of the lock icon
  837. *
  838. * @param $content what is it that we want to (un)lock: forum category, forum, thread, post
  839. * @param $id the id of the content we want to (un)lock
  840. * @param $current_visibility_status what is the current status of the visibility (0 = invisible, 1 = visible)
  841. * @return void display the lock HTML.
  842. *
  843. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  844. * @version february 2006, dokeos 1.8
  845. */
  846. function display_lock_unlock_icon($content, $id, $current_lock_status, $additional_url_parameters = '')
  847. {
  848. $id = intval($id);
  849. //check if the forum is blocked due
  850. if ($content == 'thread') {
  851. if (api_resource_is_locked_by_gradebook($id, LINK_FORUM_THREAD)) {
  852. echo Display::return_icon('lock_na.png', get_lang('ResourceLockedByGradebook'), array(), ICON_SIZE_SMALL);
  853. return;
  854. }
  855. }
  856. if ($current_lock_status == '1') {
  857. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&amp;';
  858. if (is_array($additional_url_parameters)) {
  859. foreach ($additional_url_parameters as $key => $value) {
  860. echo $key.'='.$value.'&amp;';
  861. }
  862. }
  863. echo 'action=unlock&amp;content='.$content.'&amp;id='.$id.'">'.Display::return_icon(
  864. 'lock.png',
  865. get_lang('Unlock'),
  866. array(),
  867. ICON_SIZE_SMALL
  868. ).'</a>';
  869. }
  870. if ($current_lock_status == '0') {
  871. echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&amp;';
  872. if (is_array($additional_url_parameters)) {
  873. foreach ($additional_url_parameters as $key => $value) {
  874. echo $key.'='.$value.'&amp;';
  875. }
  876. }
  877. echo 'action=lock&amp;content='.$content.'&amp;id='.$id.'">'.Display::return_icon(
  878. 'unlock.png',
  879. get_lang('Lock'),
  880. array(),
  881. ICON_SIZE_SMALL
  882. ).'</a>';
  883. }
  884. }
  885. /**
  886. * This function takes care of the display of the up and down icon
  887. *
  888. * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  889. * @param $id is the id of the item we want to display the icons for
  890. * @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)
  891. * The key of this $list array is the id of the item.
  892. *
  893. * @return void HTML
  894. *
  895. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  896. * @version february 2006, dokeos 1.8
  897. */
  898. function display_up_down_icon($content, $id, $list)
  899. {
  900. $id = strval(intval($id));
  901. $total_items = count($list);
  902. $position = 0;
  903. $internal_counter = 0;
  904. if (is_array($list)) {
  905. foreach ($list as $key => $listitem) {
  906. $internal_counter++;
  907. if ($id == $key) {
  908. $position = $internal_counter;
  909. }
  910. }
  911. }
  912. if ($position > 1) {
  913. $return_value = '<a href="'.api_get_self().'?'.api_get_cidreq().'&amp;gidReq='.Security::remove_XSS(
  914. $_GET['gidReq']
  915. ).'&action=move&amp;direction=up&amp;content='.$content.'&amp;forumcategory='.Security::remove_XSS(
  916. $_GET['forumcategory']
  917. ).'&amp;id='.$id.'" title="'.get_lang('MoveUp').'">'.Display::return_icon(
  918. 'up.png',
  919. get_lang('MoveUp'),
  920. array(),
  921. ICON_SIZE_SMALL
  922. ).'</a>';
  923. } else {
  924. $return_value = Display::return_icon('up_na.png', '-', array(), ICON_SIZE_SMALL);
  925. }
  926. if ($position < $total_items) {
  927. $return_value .= '<a href="'.api_get_self().'?'.api_get_cidreq().'&amp;gidReq='.Security::remove_XSS(
  928. $_GET['gidReq']
  929. ).'&action=move&amp;direction=down&amp;content='.$content.'&amp;forumcategory='.Security::remove_XSS(
  930. $_GET['forumcategory']
  931. ).'&amp;id='.$id.'" title="'.get_lang('MoveDown').'" >'.Display::return_icon(
  932. 'down.png',
  933. get_lang('MoveDown'),
  934. array(),
  935. ICON_SIZE_SMALL
  936. ).'</a>';
  937. } else {
  938. $return_value .= Display::return_icon('down_na.png', '-', array(), ICON_SIZE_SMALL);
  939. }
  940. echo $return_value;
  941. }
  942. /**
  943. * This function changes the visibility in the database (item_property)
  944. *
  945. * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  946. * @param $id the id of the content we want to make invisible
  947. * @param $target_visibility what is the current status of the visibility (0 = invisible, 1 = visible)
  948. *
  949. * @todo change the get parameter so that it matches the tool constants.
  950. * @todo check if api_item_property_update returns true or false => returnmessage depends on it.
  951. * @todo move to itemmanager
  952. *
  953. * @return string language variable
  954. *
  955. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  956. * @version february 2006, dokeos 1.8
  957. */
  958. function change_visibility($content, $id, $target_visibility)
  959. {
  960. $_course = api_get_course_info();
  961. $constants = array('forumcategory' => TOOL_FORUM_CATEGORY, 'forum' => TOOL_FORUM, 'thread' => TOOL_FORUM_THREAD);
  962. api_item_property_update(
  963. $_course,
  964. $constants[$content],
  965. $id,
  966. $target_visibility,
  967. api_get_user_id()
  968. ); // Note: Check if this returns true or false => returnmessage depends on it.
  969. if ($target_visibility == 'visible') {
  970. handle_mail_cue($content, $id);
  971. }
  972. return get_lang('VisibilityChanged');
  973. }
  974. /**
  975. * This function changes the lock status in the database
  976. *
  977. * @param $content what is it that we want to (un)lock: forum category, forum, thread, post
  978. * @param $id the id of the content we want to (un)lock
  979. * @param $action do we lock (=>locked value in db = 1) or unlock (=> locked value in db = 0)
  980. * @return string, language variable
  981. *
  982. * @todo move to itemmanager
  983. *
  984. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  985. * @version february 2006, dokeos 1.8
  986. */
  987. function change_lock_status($content, $id, $action)
  988. {
  989. $table_categories = Database :: get_course_table(TABLE_FORUM_CATEGORY);
  990. $table_forums = Database :: get_course_table(TABLE_FORUM);
  991. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  992. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  993. // Determine the relevant table.
  994. if ($content == 'forumcategory') {
  995. $table = $table_categories;
  996. $id_field = 'cat_id';
  997. } elseif ($content == 'forum') {
  998. $table = $table_forums;
  999. $id_field = 'forum_id';
  1000. } elseif ($content == 'thread') {
  1001. $table = $table_threads;
  1002. $id_field = 'thread_id';
  1003. } else {
  1004. return get_lang('Error');
  1005. }
  1006. // Determine what we are doing => defines the value for the database and the return message.
  1007. if ($action == 'lock') {
  1008. $db_locked = 1;
  1009. $return_message = get_lang('Locked');
  1010. } elseif ($action == 'unlock') {
  1011. $db_locked = 0;
  1012. $return_message = get_lang('Unlocked');
  1013. } else {
  1014. return get_lang('Error');
  1015. }
  1016. $course_id = api_get_course_int_id();
  1017. // Doing the change in the database
  1018. $sql = "UPDATE $table SET locked='".Database::escape_string(
  1019. $db_locked
  1020. )."' WHERE c_id = $course_id AND $id_field='".Database::escape_string($id)."'";
  1021. if (Database::query($sql)) {
  1022. return $return_message;
  1023. } else {
  1024. return get_lang('Error');
  1025. }
  1026. }
  1027. /**
  1028. * This function moves a forum or a forum category up or down
  1029. *
  1030. * @param $content what is it that we want to make (in)visible: forum category, forum, thread, post
  1031. * @param $direction do we want to move it up or down.
  1032. * @param $id the id of the content we want to make invisible
  1033. * @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
  1034. * the item_property table but does have one in the forum table.
  1035. * @return string language variable
  1036. *
  1037. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1038. * @version february 2006, dokeos 1.8
  1039. */
  1040. function move_up_down($content, $direction, $id)
  1041. {
  1042. $table_categories = Database :: get_course_table(TABLE_FORUM_CATEGORY);
  1043. $table_forums = Database :: get_course_table(TABLE_FORUM);
  1044. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  1045. $course_id = api_get_course_int_id();
  1046. // Determine which field holds the sort order.
  1047. if ($content == 'forumcategory') {
  1048. $table = $table_categories;
  1049. $sort_column = 'cat_order';
  1050. $id_column = 'cat_id';
  1051. $sort_column = 'cat_order';
  1052. } elseif ($content == 'forum') {
  1053. $table = $table_forums;
  1054. $sort_column = 'forum_order';
  1055. $id_column = 'forum_id';
  1056. $sort_column = 'forum_order';
  1057. // We also need the forum_category of this forum.
  1058. $sql = "SELECT forum_category FROM $table_forums WHERE c_id = $course_id AND forum_id=".Database::escape_string(
  1059. $id
  1060. );
  1061. $result = Database::query($sql);
  1062. $row = Database::fetch_array($result);
  1063. $forum_category = $row['forum_category'];
  1064. } else {
  1065. return get_lang('Error');
  1066. }
  1067. // Determine the need for sorting ascending or descending order.
  1068. if ($direction == 'down') {
  1069. $sort_direction = 'ASC';
  1070. } elseif ($direction == 'up') {
  1071. $sort_direction = 'DESC';
  1072. } else {
  1073. return get_lang('Error');
  1074. }
  1075. // The SQL statement
  1076. if ($content == 'forumcategory') {
  1077. $sql = "SELECT * FROM ".$table_categories." forum_categories, ".$table_item_property." item_properties
  1078. WHERE
  1079. forum_categories.c_id = $course_id AND
  1080. item_properties.c_id = $course_id AND
  1081. forum_categories.cat_id=item_properties.ref
  1082. AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  1083. ORDER BY forum_categories.cat_order $sort_direction";
  1084. }
  1085. if ($content == 'forum') {
  1086. $sql = "SELECT * FROM ".$table." WHERE c_id = $course_id AND forum_category='".Database::escape_string(
  1087. $forum_category
  1088. )."' ORDER BY forum_order $sort_direction";
  1089. }
  1090. // echo $sql.'<br />';
  1091. // Finding the items that need to be switched.
  1092. $result = Database::query($sql);
  1093. $found = false;
  1094. while ($row = Database::fetch_array($result)) {
  1095. //echo $row[$id_column].'-';
  1096. if ($found) {
  1097. $next_id = $row[$id_column];
  1098. $next_sort = $row[$sort_column];
  1099. $found = false;
  1100. }
  1101. if ($id == $row[$id_column]) {
  1102. $this_id = $id;
  1103. $this_sort = $row[$sort_column];
  1104. $found = true;
  1105. }
  1106. }
  1107. // Committing the switch.
  1108. // We do an extra check if we do not have illegal values. If your remove this if statment you will
  1109. // be able to mess with the sorting by refreshing the page over and over again.
  1110. if ($this_sort != '' && $next_sort != '' && $next_id != '' && $this_id != '') {
  1111. $sql_update1 = "UPDATE $table SET $sort_column='".Database::escape_string(
  1112. $this_sort
  1113. )."' WHERE c_id = $course_id AND $id_column='".Database::escape_string($next_id)."'";
  1114. $sql_update2 = "UPDATE $table SET $sort_column='".Database::escape_string(
  1115. $next_sort
  1116. )."' WHERE c_id = $course_id AND $id_column='".Database::escape_string($this_id)."'";
  1117. Database::query($sql_update1);
  1118. Database::query($sql_update2);
  1119. }
  1120. return get_lang(ucfirst($content).'Moved');
  1121. }
  1122. /**
  1123. * This function returns a piece of html code that make the links grey (=invisible for the student)
  1124. *
  1125. * @param boolean 0/1: 0 = invisible, 1 = visible
  1126. * @return string language variable
  1127. *
  1128. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1129. * @version february 2006, dokeos 1.8
  1130. */
  1131. function class_visible_invisible($current_visibility_status)
  1132. {
  1133. if ($current_visibility_status == '0') {
  1134. return 'class="invisible"';
  1135. }
  1136. }
  1137. /**
  1138. * Retrieve all the information off the forum categories (or one specific) for the current course.
  1139. * The categories are sorted according to their sorting order (cat_order
  1140. *
  1141. * @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.
  1142. * @return an array containing all the information about all the forum categories
  1143. *
  1144. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1145. * @version february 2006, dokeos 1.8
  1146. */
  1147. function get_forum_categories($id = '')
  1148. {
  1149. $table_categories = Database :: get_course_table(TABLE_FORUM_CATEGORY);
  1150. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  1151. $forum_categories_list = array();
  1152. // Condition for the session
  1153. $session_id = api_get_session_id();
  1154. $condition_session = api_get_session_condition($session_id);
  1155. $course_id = api_get_course_int_id();
  1156. $condition_session .= "AND forum_categories.c_id = $course_id AND item_properties.c_id = $course_id";
  1157. if ($id == '') {
  1158. $sql = "SELECT * FROM ".$table_categories." forum_categories, ".$table_item_property." item_properties
  1159. WHERE forum_categories.cat_id=item_properties.ref
  1160. AND item_properties.visibility=1
  1161. AND item_properties.tool='".TOOL_FORUM_CATEGORY."' $condition_session
  1162. ORDER BY forum_categories.cat_order ASC";
  1163. if (is_allowed_to_edit()) {
  1164. $sql = "SELECT * FROM ".$table_categories." forum_categories, ".$table_item_property." item_properties
  1165. WHERE forum_categories.cat_id=item_properties.ref
  1166. AND item_properties.visibility<>2
  1167. AND item_properties.tool='".TOOL_FORUM_CATEGORY."' $condition_session
  1168. ORDER BY forum_categories.cat_order ASC";
  1169. }
  1170. } else {
  1171. $sql = "SELECT * FROM ".$table_categories." forum_categories, ".$table_item_property." item_properties
  1172. WHERE forum_categories.cat_id=item_properties.ref
  1173. AND item_properties.tool='".TOOL_FORUM_CATEGORY."'
  1174. AND forum_categories.cat_id='".Database::escape_string($id)."' $condition_session
  1175. ORDER BY forum_categories.cat_order ASC";
  1176. }
  1177. $result = Database::query($sql);
  1178. while ($row = Database::fetch_array($result)) {
  1179. if ($id == '') {
  1180. $forum_categories_list[$row['cat_id']] = $row;
  1181. } else {
  1182. $forum_categories_list = $row;
  1183. }
  1184. }
  1185. return $forum_categories_list;
  1186. }
  1187. /**
  1188. * This function retrieves all the fora in a given forum category
  1189. *
  1190. * @param integer $cat_id the id of the forum category
  1191. * @return an array containing all the information about the forums (regardless of their category)
  1192. *
  1193. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1194. * @version february 2006, dokeos 1.8
  1195. */
  1196. function get_forums_in_category($cat_id)
  1197. {
  1198. $table_forums = Database :: get_course_table(TABLE_FORUM);
  1199. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  1200. $forum_list = array();
  1201. $course_id = api_get_course_int_id();
  1202. $sql = "SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1203. WHERE forum.forum_category='".Database::escape_string($cat_id)."'
  1204. AND forum.forum_id=item_properties.ref
  1205. AND item_properties.visibility=1
  1206. AND item_properties.c_id = $course_id
  1207. AND item_properties.tool='".TOOL_FORUM."' AND
  1208. forum.c_id = $course_id
  1209. ORDER BY forum.forum_order ASC";
  1210. if (is_allowed_to_edit()) {
  1211. $sql = "SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1212. WHERE forum.forum_category = '".Database::escape_string($cat_id)."' AND
  1213. forum.forum_id = item_properties.ref AND
  1214. item_properties.visibility<>2 AND
  1215. item_properties.tool = '".TOOL_FORUM."' AND
  1216. item_properties.c_id = $course_id AND
  1217. forum.c_id = $course_id
  1218. ORDER BY forum_order ASC";
  1219. }
  1220. $result = Database::query($sql);
  1221. while ($row = Database::fetch_array($result)) {
  1222. $forum_list[$row['forum_id']] = $row;
  1223. }
  1224. return $forum_list;
  1225. }
  1226. /**
  1227. * Retrieve all the forums (regardless of their category) or of only one. The forums are sorted according to the forum_order.
  1228. * Since it does not take the forum category into account there probably will be two or more forums that have forum_order=1, ...
  1229. * @param int forum id
  1230. * @param string course db name
  1231. * @return an array containing all the information about the forums (regardless of their category)
  1232. * @todo check $sql4 because this one really looks fishy.
  1233. *
  1234. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1235. * @version february 2006, dokeos 1.8
  1236. */
  1237. function get_forums($id = '', $course_code = '')
  1238. {
  1239. $course_info = api_get_course_info($course_code);
  1240. $table_users = Database :: get_main_table(TABLE_MAIN_USER);
  1241. $table_forums = Database :: get_course_table(TABLE_FORUM);
  1242. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  1243. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  1244. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  1245. // GETTING ALL THE FORUMS
  1246. // Condition for the session
  1247. $session_id = api_get_session_id();
  1248. $condition_session = api_get_session_condition($session_id);
  1249. $course_id = $course_info['real_id'];
  1250. $forum_list = array();
  1251. if ($id == '') {
  1252. // Student
  1253. // Select all the forum information of all forums (that are visible to students).
  1254. $sql = "SELECT * FROM $table_forums forum , ".$table_item_property." item_properties
  1255. WHERE forum.forum_id=item_properties.ref
  1256. AND item_properties.visibility=1
  1257. AND item_properties.tool='".TOOL_FORUM."'
  1258. $condition_session AND forum.c_id = $course_id AND item_properties.c_id = $course_id
  1259. ORDER BY forum.forum_order ASC";
  1260. // Select the number of threads of the forums (only the threads that are visible).
  1261. $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  1262. WHERE threads.thread_id=item_properties.ref
  1263. AND item_properties.visibility=1
  1264. AND item_properties.tool='".TOOL_FORUM_THREAD."' AND threads.c_id = $course_id AND item_properties.c_id = $course_id
  1265. GROUP BY threads.forum_id";
  1266. // Select the number of posts of the forum (post that are visible and that are in a thread that is visible).
  1267. $sql3 = "SELECT count(*) AS number_of_posts, posts.forum_id FROM $table_posts posts, $table_threads threads, ".$table_item_property." item_properties
  1268. WHERE posts.visible=1
  1269. AND posts.thread_id=threads.thread_id
  1270. AND threads.thread_id=item_properties.ref
  1271. AND item_properties.visibility=1
  1272. AND item_properties.tool='".TOOL_FORUM_THREAD."' AND threads.c_id = $course_id AND posts.c_id = $course_id AND item_properties.c_id = $course_id
  1273. GROUP BY threads.forum_id";
  1274. //-------------- Course Admin -----------------//
  1275. if (is_allowed_to_edit()) {
  1276. // Select all the forum information of all forums (that are not deleted).
  1277. $sql = "SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  1278. WHERE forum.forum_id=item_properties.ref
  1279. AND item_properties.visibility<>2
  1280. AND item_properties.tool='".TOOL_FORUM."'
  1281. $condition_session AND forum.c_id = $course_id AND item_properties.c_id = $course_id
  1282. ORDER BY forum_order ASC";
  1283. //echo $sql.'<hr />';
  1284. // Select the number of threads of the forums (only the threads that are not deleted).
  1285. $sql2 = "SELECT count(*) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  1286. WHERE threads.thread_id=item_properties.ref
  1287. AND item_properties.visibility<>2
  1288. AND item_properties.tool='".TOOL_FORUM_THREAD."' AND threads.c_id = $course_id AND item_properties.c_id = $course_id
  1289. GROUP BY threads.forum_id";
  1290. //echo $sql2.'<hr />';
  1291. // Select the number of posts of the forum.
  1292. $sql3 = "SELECT count(*) AS number_of_posts, posts.forum_id FROM $table_posts posts, $table_threads threads, ".$table_item_property." item_properties
  1293. WHERE posts.thread_id=threads.thread_id
  1294. AND threads.thread_id=item_properties.ref
  1295. AND item_properties.visibility=1
  1296. AND item_properties.tool='".TOOL_FORUM_THREAD."' AND posts.c_id = $course_id AND threads.c_id = $course_id AND item_properties.c_id = $course_id
  1297. GROUP BY threads.forum_id";
  1298. //echo $sql3.'<hr />';
  1299. }
  1300. } else {
  1301. // GETTING ONE SPECIFIC FORUM
  1302. // 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
  1303. // 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
  1304. // when editing a forum (and for the moment it is the only place where we use this part of the function)
  1305. //
  1306. // Select all the forum information of the given forum (that is not deleted).
  1307. $sql = "SELECT * FROM $table_forums forum , ".$table_item_property." item_properties
  1308. WHERE forum.forum_id=item_properties.ref
  1309. AND forum_id='".Database::escape_string($id)."'
  1310. AND item_properties.visibility<>2
  1311. AND item_properties.tool='".TOOL_FORUM."'
  1312. $condition_session AND forum.c_id = $course_id AND item_properties.c_id = $course_id
  1313. ORDER BY forum_order ASC";
  1314. // Select the number of threads of the forum.
  1315. $sql2 = "SELECT count(*) AS number_of_threads, forum_id FROM $table_threads
  1316. WHERE forum_id=".Database::escape_string($id)." AND c_id = $course_id
  1317. GROUP BY forum_id";
  1318. // Select the number of posts of the forum.
  1319. $sql3 = "SELECT count(*) AS number_of_posts, forum_id FROM $table_posts
  1320. WHERE forum_id=".Database::escape_string($id)." AND c_id = $course_id
  1321. GROUP BY forum_id";
  1322. // Select the last post and the poster (note: this is probably no longer needed).
  1323. $sql4 = "SELECT post.post_id, post.forum_id, post.poster_id, post.poster_name, post.post_date, users.lastname, users.firstname
  1324. FROM $table_posts post, $table_users users
  1325. WHERE forum_id=".Database::escape_string($id)."
  1326. AND post.poster_id=users.user_id AND post.c_id = $course_id
  1327. GROUP BY post.forum_id
  1328. ORDER BY post.post_id ASC";
  1329. }
  1330. // Handling all the forum information.
  1331. $result = Database::query($sql);
  1332. while ($row = Database::fetch_array($result)) {
  1333. if ($id == '') {
  1334. $forum_list[$row['forum_id']] = $row;
  1335. } else {
  1336. $forum_list = $row;
  1337. }
  1338. }
  1339. // Handling the threadcount information.
  1340. $result2 = Database::query($sql2);
  1341. while ($row2 = Database::fetch_array($result2)) {
  1342. if ($id == '') {
  1343. $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
  1344. } else {
  1345. $forum_list['number_of_threads'] = $row2['number_of_threads'];
  1346. }
  1347. }
  1348. // Handling the postcount information.
  1349. $result3 = Database::query($sql3);
  1350. while ($row3 = Database::fetch_array($result3)) {
  1351. if ($id == '') {
  1352. if (array_key_exists(
  1353. $row3['forum_id'],
  1354. $forum_list
  1355. )
  1356. ) { // This is needed because sql3 takes also the deleted forums into account.
  1357. $forum_list[$row3['forum_id']]['number_of_posts'] = $row3['number_of_posts'];
  1358. }
  1359. } else {
  1360. $forum_list['number_of_posts'] = $row3['number_of_posts'];
  1361. }
  1362. }
  1363. // Finding the last post information (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname).
  1364. if ($id == '') {
  1365. if (is_array($forum_list)) {
  1366. foreach ($forum_list as $key => $value) {
  1367. $last_post_info_of_forum = get_last_post_information($key, api_is_allowed_to_edit(), $course_id);
  1368. $forum_list[$key]['last_post_id'] = $last_post_info_of_forum['last_post_id'];
  1369. $forum_list[$key]['last_poster_id'] = $last_post_info_of_forum['last_poster_id'];
  1370. $forum_list[$key]['last_post_date'] = $last_post_info_of_forum['last_post_date'];
  1371. $forum_list[$key]['last_poster_name'] = $last_post_info_of_forum['last_poster_name'];
  1372. $forum_list[$key]['last_poster_lastname'] = $last_post_info_of_forum['last_poster_lastname'];
  1373. $forum_list[$key]['last_poster_firstname'] = $last_post_info_of_forum['last_poster_firstname'];
  1374. }
  1375. } else {
  1376. $forum_list = array();
  1377. }
  1378. } else {
  1379. $last_post_info_of_forum = get_last_post_information($id, api_is_allowed_to_edit(), $course_id);
  1380. $forum_list['last_post_id'] = $last_post_info_of_forum['last_post_id'];
  1381. $forum_list['last_poster_id'] = $last_post_info_of_forum['last_poster_id'];
  1382. $forum_list['last_post_date'] = $last_post_info_of_forum['last_post_date'];
  1383. $forum_list['last_poster_name'] = $last_post_info_of_forum['last_poster_name'];
  1384. $forum_list['last_poster_lastname'] = $last_post_info_of_forum['last_poster_lastname'];
  1385. $forum_list['last_poster_firstname'] = $last_post_info_of_forum['last_poster_firstname'];
  1386. }
  1387. return $forum_list;
  1388. }
  1389. function get_last_post_by_thread($course_id, $thread_id, $forum_id, $show_visible = true)
  1390. {
  1391. if (empty($thread_id) || empty($forum_id) || empty($course_id)) {
  1392. return false;
  1393. }
  1394. $thread_id = intval($thread_id);
  1395. $forum_id = intval($forum_id);
  1396. $course_id = intval($course_id);
  1397. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  1398. $sql = "SELECT * FROM $table_posts
  1399. WHERE c_id = $course_id AND thread_id = $thread_id AND forum_id = $forum_id";
  1400. if ($show_visible == false) {
  1401. $sql .= " AND visible = 1 ";
  1402. }
  1403. $sql .= " ORDER BY post_id DESC LIMIT 1";
  1404. $result = Database::query($sql);
  1405. if (Database::num_rows($result)) {
  1406. return Database::fetch_array($result, 'ASSOC');
  1407. } else {
  1408. return false;
  1409. }
  1410. }
  1411. /**
  1412. * This function gets all the last post information of a certain forum
  1413. *
  1414. * @param int $forum_id the id of the forum we want to know the last post information of.
  1415. * @param bool $show_invisibles
  1416. * @param string course db name
  1417. * @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)
  1418. *
  1419. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1420. * @version february 2006, dokeos 1.8
  1421. */
  1422. function get_last_post_information($forum_id, $show_invisibles = false, $course_id = null)
  1423. {
  1424. if (!isset($course_id)) {
  1425. $course_id = api_get_course_int_id();
  1426. } else {
  1427. $course_id = intval($course_id);
  1428. }
  1429. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  1430. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  1431. $table_users = Database :: get_main_table(TABLE_MAIN_USER);
  1432. $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
  1433. FROM $table_posts post, $table_users users, $table_item_property thread_properties, $table_item_property forum_properties
  1434. WHERE post.forum_id=".Database::escape_string($forum_id)."
  1435. AND post.poster_id=users.user_id
  1436. AND post.thread_id=thread_properties.ref
  1437. AND thread_properties.tool='".TOOL_FORUM_THREAD."'
  1438. AND post.forum_id=forum_properties.ref
  1439. AND forum_properties.tool='".TOOL_FORUM."'
  1440. AND post.c_id = $course_id AND
  1441. thread_properties.c_id = $course_id AND
  1442. forum_properties.c_id = $course_id
  1443. ORDER BY post.post_id DESC";
  1444. $result = Database::query($sql);
  1445. if ($show_invisibles) {
  1446. $row = Database::fetch_array($result);
  1447. $return_array['last_post_id'] = $row['post_id'];
  1448. $return_array['last_poster_id'] = $row['poster_id'];
  1449. $return_array['last_post_date'] = $row['post_date'];
  1450. $return_array['last_poster_name'] = $row['poster_name'];
  1451. $return_array['last_poster_lastname'] = $row['lastname'];
  1452. $return_array['last_poster_firstname'] = $row['firstname'];
  1453. return $return_array;
  1454. } else {
  1455. // 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).
  1456. while ($row = Database::fetch_array($result)) {
  1457. if ($row['visible'] == '1' && $row['thread_visibility'] == '1' && $row['forum_visibility'] == '1') {
  1458. $return_array['last_post_id'] = $row['post_id'];
  1459. $return_array['last_poster_id'] = $row['poster_id'];
  1460. $return_array['last_post_date'] = $row['post_date'];
  1461. $return_array['last_poster_name'] = $row['poster_name'];
  1462. $return_array['last_poster_lastname'] = $row['lastname'];
  1463. $return_array['last_poster_firstname'] = $row['firstname'];
  1464. return $return_array;
  1465. }
  1466. }
  1467. }
  1468. }
  1469. /**
  1470. * Retrieve all the threads of a given forum
  1471. *
  1472. * @param int forum id
  1473. * @param string course db name
  1474. * @return an array containing all the information about the threads
  1475. *
  1476. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1477. * @version february 2006, dokeos 1.8
  1478. */
  1479. function get_threads($forum_id, $course_code = null)
  1480. {
  1481. $course_info = api_get_course_info($course_code);
  1482. if (empty($course_info)) {
  1483. return array();
  1484. }
  1485. $course_id = $course_info['real_id'];
  1486. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  1487. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  1488. $table_users = Database :: get_main_table(TABLE_MAIN_USER);
  1489. $thread_list = array();
  1490. // important note: it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
  1491. // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
  1492. // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
  1493. // This is why it is added to the end of the field selection
  1494. $sql = "SELECT thread.*,
  1495. item_properties.*,
  1496. users.firstname,
  1497. users.lastname,
  1498. users.user_id,
  1499. thread.locked as locked
  1500. FROM $table_threads thread
  1501. INNER JOIN $table_item_property item_properties
  1502. ON thread.thread_id=item_properties.ref AND
  1503. item_properties.c_id = $course_id AND
  1504. thread.c_id = $course_id AND
  1505. item_properties.tool='".TABLE_FORUM_THREAD."'
  1506. LEFT JOIN $table_users users
  1507. ON thread.thread_poster_id=users.user_id
  1508. WHERE
  1509. item_properties.visibility='1' AND
  1510. thread.forum_id='".Database::escape_string($forum_id)."'
  1511. ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
  1512. if (is_allowed_to_edit()) {
  1513. // important note: it might seem a little bit awkward that we have 'thread.locked as locked' in the sql statement
  1514. // because we also have thread.* in it. This is because thread has a field locked and post also has the same field
  1515. // since we are merging these we would have the post.locked value but in fact we want the thread.locked value
  1516. // This is why it is added to the end of the field selection
  1517. $sql = "SELECT thread.*,
  1518. item_properties.*,
  1519. users.firstname,
  1520. users.lastname,
  1521. users.user_id,
  1522. thread.locked as locked
  1523. FROM $table_threads thread
  1524. INNER JOIN $table_item_property item_properties
  1525. ON thread.thread_id=item_properties.ref AND
  1526. item_properties.c_id = $course_id AND
  1527. thread.c_id = $course_id AND
  1528. item_properties.tool='".TABLE_FORUM_THREAD."'
  1529. LEFT JOIN $table_users users
  1530. ON thread.thread_poster_id=users.user_id
  1531. WHERE
  1532. item_properties.visibility<>2 AND
  1533. thread.forum_id='".Database::escape_string($forum_id)."'
  1534. ORDER BY thread.thread_sticky DESC, thread.thread_date DESC";
  1535. }
  1536. $result = Database::query($sql);
  1537. while ($row = Database::fetch_array($result, 'ASSOC')) {
  1538. $thread_list[] = $row;
  1539. }
  1540. return $thread_list;
  1541. }
  1542. /**
  1543. * Retrieve all posts of a given thread
  1544. *
  1545. * @return an array containing all the information about the posts of a given thread
  1546. *
  1547. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1548. * @version february 2006, dokeos 1.8
  1549. */
  1550. function get_posts($thread_id)
  1551. {
  1552. $table_users = Database :: get_main_table(TABLE_MAIN_USER);
  1553. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  1554. $course_id = api_get_course_int_id();
  1555. // note: change these SQL so that only the relevant fields of the user table are used
  1556. if (api_is_allowed_to_edit(null, true)) {
  1557. $sql = "SELECT * FROM $table_posts posts
  1558. LEFT JOIN $table_users users
  1559. ON posts.poster_id=users.user_id
  1560. WHERE
  1561. c_id = $course_id AND
  1562. posts.thread_id='".Database::escape_string($thread_id)."'
  1563. ORDER BY posts.post_id ASC";
  1564. } else {
  1565. // students can only se the posts that are approved (posts.visible='1')
  1566. $sql = "SELECT * FROM $table_posts posts
  1567. LEFT JOIN $table_users users
  1568. ON posts.poster_id=users.user_id
  1569. WHERE
  1570. c_id = $course_id AND
  1571. posts.thread_id='".Database::escape_string($thread_id)."'
  1572. AND posts.visible='1'
  1573. ORDER BY posts.post_id ASC";
  1574. }
  1575. $result = Database::query($sql);
  1576. while ($row = Database::fetch_array($result)) {
  1577. $post_list[] = $row;
  1578. }
  1579. return $post_list;
  1580. }
  1581. // NEW TOPIC FUNCTIONS
  1582. /**
  1583. * This function retrieves all the information of a post
  1584. *
  1585. * @param $forum_id integer that indicates the forum
  1586. * @return array returns
  1587. *
  1588. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1589. * @version february 2006, dokeos 1.8
  1590. */
  1591. function get_post_information($post_id)
  1592. {
  1593. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  1594. $table_users = Database :: get_main_table(TABLE_MAIN_USER);
  1595. $course_id = api_get_course_int_id();
  1596. $sql = "SELECT * FROM ".$table_posts."posts, ".$table_users." users
  1597. WHERE c_id = $course_id AND posts.poster_id=users.user_id AND posts.post_id='".Database::escape_string(
  1598. $post_id
  1599. )."'";
  1600. $result = Database::query($sql);
  1601. $row = Database::fetch_array($result);
  1602. return $row;
  1603. }
  1604. /**
  1605. * This function retrieves all the information of a thread
  1606. *
  1607. * @param $forum_id integer that indicates the forum
  1608. * @return array returns
  1609. *
  1610. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1611. * @version february 2006, dokeos 1.8
  1612. */
  1613. function get_thread_information($thread_id)
  1614. {
  1615. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  1616. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  1617. $course_id = api_get_course_int_id();
  1618. $sql = "SELECT * FROM ".$table_threads." threads, ".$table_item_property." item_properties
  1619. WHERE item_properties.tool= '".TOOL_FORUM_THREAD."' AND
  1620. item_properties.c_id = $course_id AND
  1621. item_properties.ref = '".Database::escape_string($thread_id)."' AND
  1622. threads.thread_id = '".Database::escape_string($thread_id)."' AND
  1623. threads.c_id = $course_id
  1624. ";
  1625. $result = Database::query($sql);
  1626. $row = Database::fetch_array($result);
  1627. return $row;
  1628. }
  1629. /**
  1630. * This function retrieves forum thread users details
  1631. * @param int Thread ID
  1632. * @param string Course DB name (optional)
  1633. * @return resource array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
  1634. * @author Christian Fasanando <christian.fasanando@dokeos.com>,
  1635. * @todo this function need to be improved
  1636. * @version octubre 2008, dokeos 1.8
  1637. */
  1638. function get_thread_users_details($thread_id)
  1639. {
  1640. $t_posts = Database :: get_course_table(TABLE_FORUM_POST);
  1641. $t_users = Database :: get_main_table(TABLE_MAIN_USER);
  1642. $t_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  1643. $t_session_rel_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
  1644. $course_code = api_get_course_id();
  1645. $course_code = Database::escape_string($course_code);
  1646. $course_id = api_get_course_int_id();
  1647. $is_western_name_order = api_is_western_name_order();
  1648. if ($is_western_name_order) {
  1649. $orderby = 'ORDER BY user.firstname, user.lastname ';
  1650. } else {
  1651. $orderby = 'ORDER BY user.lastname, user.firstname';
  1652. }
  1653. if (api_get_session_id()) {
  1654. $session_info = api_get_session_info(api_get_session_id());
  1655. $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
  1656. //not showing coaches
  1657. $sql = "SELECT DISTINCT user.user_id, user.lastname, user.firstname, thread_id
  1658. FROM $t_posts , $t_users user, $t_session_rel_user session_rel_user_rel_course
  1659. WHERE poster_id = user.user_id AND
  1660. user.user_id = session_rel_user_rel_course.id_user AND
  1661. session_rel_user_rel_course.status<>'2' AND
  1662. session_rel_user_rel_course.id_user NOT IN ($user_to_avoid) AND
  1663. thread_id = '".Database::escape_string($thread_id)."' AND
  1664. id_session = '".api_get_session_id()."' AND
  1665. c_id = $course_id AND
  1666. course_code = '".$course_code."' $orderby ";
  1667. } else {
  1668. $sql = "SELECT DISTINCT user.user_id, user.lastname, user.firstname, thread_id
  1669. FROM $t_posts, $t_users user, $t_course_user course_user
  1670. WHERE poster_id = user.user_id AND
  1671. course_user.c_id = $t_posts.c_id
  1672. user.user_id = course_user.user_id AND
  1673. course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
  1674. thread_id = '".Database::escape_string($thread_id)."' AND
  1675. course_user.status NOT IN('1') AND
  1676. course_user.c_id = $course_id
  1677. $orderby";
  1678. }
  1679. $result = Database::query($sql);
  1680. return $result;
  1681. }
  1682. /**
  1683. * This function retrieves forum thread users qualify
  1684. * @param int Thread ID
  1685. * @param string Course DB name (optional)
  1686. * @return array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
  1687. * @author Jhon Hinojosa<jhon.hinojosa@dokeos.com>,
  1688. * @todo this function need to be improved
  1689. * @version octubre 2008, dokeos 1.8
  1690. */
  1691. function get_thread_users_qualify($thread_id)
  1692. {
  1693. $t_posts = Database :: get_course_table(TABLE_FORUM_POST);
  1694. $t_qualify = Database :: get_course_table(TABLE_FORUM_THREAD_QUALIFY);
  1695. $t_users = Database :: get_main_table(TABLE_MAIN_USER);
  1696. $t_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  1697. $t_session_rel_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
  1698. $course_id = api_get_course_int_id();
  1699. $course_code = api_get_course_id();
  1700. $course_code = Database::escape_string($course_code);
  1701. $is_western_name_order = api_is_western_name_order();
  1702. if ($is_western_name_order) {
  1703. $orderby = 'ORDER BY user.firstname, user.lastname ';
  1704. } else {
  1705. $orderby = 'ORDER BY user.lastname, user.firstname';
  1706. }
  1707. if (api_get_session_id()) {
  1708. $session_info = api_get_session_info(api_get_session_id());
  1709. $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
  1710. //not showing coaches
  1711. $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.user_id,qualify.qualify
  1712. FROM $t_posts post , $t_users user, $t_session_rel_user session_rel_user_rel_course, $t_qualify qualify
  1713. WHERE poster_id = user.user_id
  1714. AND post.poster_id = qualify.user_id
  1715. AND user.user_id = session_rel_user_rel_course.id_user
  1716. AND session_rel_user_rel_course.status<>'2'
  1717. AND session_rel_user_rel_course.id_user NOT IN ($user_to_avoid)
  1718. AND qualify.thread_id = '".Database::escape_string($thread_id)."
  1719. AND thread_id = '".Database::escape_string($thread_id)."'
  1720. AND id_session = '".api_get_session_id()."'
  1721. AND course_code = '".$course_code."' AND
  1722. qualify.c_id = $course_id AND
  1723. post.c_id = $course_id
  1724. $orderby ";
  1725. } else {
  1726. $sql = "SELECT DISTINCT post.poster_id, user.lastname, user.firstname, post.thread_id,user.user_id,qualify.qualify
  1727. FROM $t_posts post,
  1728. $t_qualify qualify,
  1729. $t_users user,
  1730. $t_course_user course_user
  1731. WHERE
  1732. post.poster_id = user.user_id
  1733. AND post.poster_id = qualify.user_id
  1734. AND user.user_id = course_user.user_id
  1735. AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
  1736. AND qualify.thread_id = '".Database::escape_string($thread_id)."'
  1737. AND post.thread_id = '".Database::escape_string($thread_id)."'
  1738. AND course_user.status not in('1')
  1739. AND course_user.c_id = $course_id AND
  1740. qualify.c_id = $course_id AND
  1741. post.c_id = $course_id
  1742. $orderby ";
  1743. }
  1744. $result = Database::query($sql);
  1745. return $result;
  1746. }
  1747. /**
  1748. * This function retrieves forum thread users not qualify
  1749. * @param int Thread ID
  1750. * @param string Course DB name (optional)
  1751. * @return array Array of type ([user_id=>w,lastname=>x,firstname=>y,thread_id=>z],[])
  1752. * @author Jhon Hinojosa<jhon.hinojosa@dokeos.com>,
  1753. * @todo i'm a horrible function fix me
  1754. * @version octubre 2008, dokeos 1.8
  1755. */
  1756. function get_thread_users_not_qualify($thread_id)
  1757. {
  1758. $t_posts = Database :: get_course_table(TABLE_FORUM_POST);
  1759. $t_qualify = Database :: get_course_table(TABLE_FORUM_THREAD_QUALIFY);
  1760. $t_users = Database :: get_main_table(TABLE_MAIN_USER);
  1761. $t_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  1762. $t_session_rel_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
  1763. $is_western_name_order = api_is_western_name_order();
  1764. if ($is_western_name_order) {
  1765. $orderby = 'ORDER BY user.firstname, user.lastname ';
  1766. } else {
  1767. $orderby = 'ORDER BY user.lastname, user.firstname';
  1768. }
  1769. $course_id = api_get_course_int_id();
  1770. $course_code = api_get_course_id();
  1771. $sql1 = "select user_id FROM $t_qualify WHERE c_id = $course_id AND thread_id = '".$thread_id."'";
  1772. $result1 = Database::query($sql1);
  1773. $cad = '';
  1774. while ($row = Database::fetch_array($result1)) {
  1775. $cad .= $row['user_id'].',';
  1776. }
  1777. if ($cad == '') {
  1778. $cad = '0';
  1779. } else {
  1780. $cad = substr($cad, 0, strlen($cad) - 1);
  1781. }
  1782. if (api_get_session_id()) {
  1783. $session_info = api_get_session_info(api_get_session_id());
  1784. $user_to_avoid = "'".$session_info['id_coach']."', '".$session_info['session_admin_id']."'";
  1785. //not showing coaches
  1786. $sql = "SELECT DISTINCT user.user_id, user.lastname, user.firstname, post.thread_id
  1787. FROM $t_posts post , $t_users user, $t_session_rel_user session_rel_user_rel_course
  1788. WHERE poster_id = user.user_id
  1789. AND user.user_id NOT IN (".$cad.")
  1790. AND user.user_id = session_rel_user_rel_course.id_user
  1791. AND session_rel_user_rel_course.status<>'2'
  1792. AND session_rel_user_rel_course.id_user NOT IN ($user_to_avoid)
  1793. AND post.thread_id = '".Database::escape_string($thread_id)."'
  1794. AND id_session = '".api_get_session_id()."'
  1795. AND course_code = '".$course_code."' AND post.c_id = $course_id $orderby ";
  1796. } else {
  1797. $sql = "SELECT DISTINCT user.user_id, user.lastname, user.firstname, post.thread_id
  1798. FROM $t_posts post, $t_users user,$t_course_user course_user
  1799. WHERE post.poster_id = user.user_id
  1800. AND user.user_id NOT IN (".$cad.")
  1801. AND user.user_id = course_user.user_id
  1802. AND course_user.relation_type<>".COURSE_RELATION_TYPE_RRHH."
  1803. AND post.thread_id = '".Database::escape_string($thread_id)."'
  1804. AND course_user.status not in('1')
  1805. AND course_user.c_id = $course_id AND post.c_id = $course_id $orderby";
  1806. }
  1807. $result = Database::query($sql);
  1808. return $result;
  1809. }
  1810. /**
  1811. * This function retrieves all the information of a given forum_id
  1812. *
  1813. * @param $forum_id integer that indicates the forum
  1814. * @return array returns
  1815. *
  1816. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1817. * @version february 2006, dokeos 1.8
  1818. *
  1819. * @deprecated this functionality is now moved to get_forums($forum_id)
  1820. */
  1821. function get_forum_information($forum_id)
  1822. {
  1823. $table_forums = Database :: get_course_table(TABLE_FORUM);
  1824. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  1825. $sql = "SELECT * FROM ".$table_forums." forums, ".$table_item_property." item_properties
  1826. WHERE item_properties.tool = '".TOOL_FORUM."' AND
  1827. item_properties.ref = '".Database::escape_string($forum_id)."' AND
  1828. item_properties.c_id = ".api_get_course_int_id()." AND
  1829. forums.forum_id = '".Database::escape_string($forum_id)."' AND
  1830. forums.c_id = ".api_get_course_int_id()."
  1831. ";
  1832. $result = Database::query($sql);
  1833. $row = Database::fetch_array($result);
  1834. $row['approval_direct_post'] = 0; // We can't anymore change this option, so it should always be activated.
  1835. return $row;
  1836. }
  1837. /**
  1838. * This function retrieves all the information of a given forumcategory id
  1839. *
  1840. * @param $forum_id integer that indicates the forum
  1841. * @return array returns if there are category or bool returns if there aren't category
  1842. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1843. * @version february 2006, dokeos 1.8
  1844. */
  1845. function get_forumcategory_information($cat_id)
  1846. {
  1847. $table_categories = Database :: get_course_table(TABLE_FORUM_CATEGORY);
  1848. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  1849. $course_id = api_get_course_int_id();
  1850. $sql = "SELECT * FROM ".$table_categories." forumcategories, ".$table_item_property." item_properties
  1851. WHERE forumcategories.c_id = $course_id AND
  1852. item_properties.c_id = $course_id AND
  1853. item_properties.tool='".TOOL_FORUM_CATEGORY."' AND
  1854. item_properties.ref='".Database::escape_string($cat_id)."' AND
  1855. forumcategories.cat_id='".Database::escape_string($cat_id)."'";
  1856. $result = Database::query($sql);
  1857. $row = Database::fetch_array($result);
  1858. return $row;
  1859. }
  1860. /**
  1861. * This function counts the number of forums inside a given category
  1862. *
  1863. * @param $cat_id the id of the forum category
  1864. * @todo an additional parameter that takes the visibility into account. For instance $countinvisible=0 would return the number
  1865. * of visible forums, $countinvisible=1 would return the number of visible and invisible forums
  1866. * @return int the number of forums inside the given category
  1867. *
  1868. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1869. * @version february 2006, dokeos 1.8
  1870. */
  1871. function count_number_of_forums_in_category($cat_id)
  1872. {
  1873. $table_forums = Database :: get_course_table(TABLE_FORUM);
  1874. $course_id = api_get_course_int_id();
  1875. $sql = "SELECT count(*) AS number_of_forums FROM ".$table_forums." WHERE c_id = $course_id AND forum_category='".Database::escape_string(
  1876. $cat_id
  1877. )."'";
  1878. $result = Database::query($sql);
  1879. $row = Database::fetch_array($result);
  1880. return $row['number_of_forums'];
  1881. }
  1882. /**
  1883. * This function stores a new thread. This is done through an entry in the forum_thread table AND
  1884. * in the forum_post table because. The threads are also stored in the item_property table. (forum posts are not (yet))
  1885. *
  1886. * @param array
  1887. * @return void HTML
  1888. *
  1889. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1890. * @version february 2006, dokeos 1.8
  1891. */
  1892. function store_thread($values)
  1893. {
  1894. global $_user;
  1895. $_course = api_get_course_info();
  1896. global $current_forum;
  1897. global $origin;
  1898. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  1899. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  1900. $course_id = api_get_course_int_id();
  1901. $gradebook = Security::remove_XSS($_GET['gradebook']);
  1902. $upload_ok = 1;
  1903. $has_attachment = false;
  1904. if (!empty($_FILES['user_upload']['name'])) {
  1905. $upload_ok = FileManager::process_uploaded_file($_FILES['user_upload']);
  1906. $has_attachment = true;
  1907. }
  1908. if ($upload_ok) {
  1909. $post_date = api_get_utc_datetime();
  1910. if ($current_forum['approval_direct_post'] == '1' && !api_is_allowed_to_edit(null, true)) {
  1911. $visible = 0; // The post has not been approved yet.
  1912. } else {
  1913. $visible = 1;
  1914. }
  1915. $clean_post_title = Database::escape_string(stripslashes($values['post_title']));
  1916. // We first store an entry in the forum_thread table because the thread_id is used in the forum_post table.
  1917. $sql = "INSERT INTO $table_threads (c_id, thread_title, forum_id, thread_poster_id, thread_poster_name, thread_date, thread_sticky,thread_title_qualify,thread_qualify_max,thread_weight,session_id)
  1918. VALUES (
  1919. ".$course_id.",
  1920. '".$clean_post_title."',
  1921. '".Database::escape_string($values['forum_id'])."',
  1922. '".Database::escape_string($_user['user_id'])."',
  1923. '".Database::escape_string(
  1924. stripslashes(isset($values['poster_name']) ? $values['poster_name'] : null)
  1925. )."',
  1926. '".Database::escape_string($post_date)."',
  1927. '".Database::escape_string(
  1928. isset($values['thread_sticky']) ? $values['thread_sticky'] : null
  1929. )."',".
  1930. "'".Database::escape_string(stripslashes($values['calification_notebook_title']))."',".
  1931. "'".Database::escape_string($values['numeric_calification'])."',".
  1932. "'".Database::escape_string($values['weight_calification'])."',".
  1933. "'".api_get_session_id()."')";
  1934. $result = Database::query($sql);
  1935. $last_thread_id = Database::insert_id();
  1936. // Add option gradebook qualify.
  1937. if (isset($values['thread_qualify_gradebook']) && 1 == $values['thread_qualify_gradebook']) {
  1938. // Add function gradebook.
  1939. $coursecode = api_get_course_id();
  1940. $resourcetype = 5;
  1941. $resourceid = $last_thread_id;
  1942. $resourcename = stripslashes($values['calification_notebook_title']);
  1943. $maxqualify = $values['numeric_calification'];
  1944. $weigthqualify = $values['weight_calification'];
  1945. $resourcedescription = '';
  1946. add_resource_to_course_gradebook(
  1947. $values['category_id'],
  1948. $coursecode,
  1949. $resourcetype,
  1950. $resourceid,
  1951. $resourcename,
  1952. $weigthqualify,
  1953. $maxqualify,
  1954. $resourcedescription,
  1955. 0,
  1956. api_get_session_id()
  1957. );
  1958. }
  1959. if ($last_thread_id) {
  1960. api_item_property_update(
  1961. $_course,
  1962. TOOL_FORUM_THREAD,
  1963. $last_thread_id,
  1964. 'ForumThreadAdded',
  1965. api_get_user_id()
  1966. );
  1967. // If the forum properties tell that the posts have to be approved we have to put the whole thread invisible,
  1968. // because otherwise the students will see the thread and not the post in the thread.
  1969. // We also have to change $visible because the post itself has to be visible in this case (otherwise the teacher would have
  1970. // to make the thread visible AND the post.
  1971. //Default behaviour
  1972. api_set_default_visibility($_course, $last_thread_id, TOOL_FORUM_THREAD);
  1973. if ($visible == 0) {
  1974. api_item_property_update($_course, TOOL_FORUM_THREAD, $last_thread_id, 'invisible', api_get_user_id());
  1975. $visible = 1;
  1976. }
  1977. }
  1978. // We now store the content in the table_post table.
  1979. $sql = "INSERT INTO $table_posts (c_id, post_title, post_text, thread_id, forum_id, poster_id, poster_name, post_date, post_notification, post_parent_id, visible)
  1980. VALUES (
  1981. ".$course_id.",
  1982. '".$clean_post_title."',
  1983. '".Database::escape_string($values['post_text'])."',
  1984. '".Database::escape_string($last_thread_id)."',
  1985. '".Database::escape_string($values['forum_id'])."',
  1986. '".Database::escape_string($_user['user_id'])."',
  1987. '".Database::escape_string(stripslashes(isset($values['poster_name']) ? $values['poster_name'] : null))."',
  1988. '".Database::escape_string($post_date)."',
  1989. '".Database::escape_string(isset($values['post_notification']) ? $values['post_notification'] : null)."','0',
  1990. '".Database::escape_string($visible)."')";
  1991. Database::query($sql);
  1992. $last_post_id = Database::insert_id();
  1993. // Now we 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).
  1994. $sql = "UPDATE $table_threads SET thread_last_post='".Database::escape_string(
  1995. $last_post_id
  1996. )."' WHERE c_id = $course_id AND thread_id='".Database::escape_string($last_thread_id)."'";
  1997. $result = Database::query($sql);
  1998. $message = get_lang('NewThreadStored');
  1999. // Storing the attachments if any.
  2000. if ($has_attachment) {
  2001. $course_dir = $_course['path'].'/upload/forum';
  2002. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  2003. $updir = $sys_course_path.$course_dir;
  2004. // Try to add an extension to the file if it hasn't one.
  2005. $new_file_name = FileManager::add_ext_on_mime(
  2006. stripslashes($_FILES['user_upload']['name']),
  2007. $_FILES['user_upload']['type']
  2008. );
  2009. // User's file name
  2010. $file_name = $_FILES['user_upload']['name'];
  2011. if (!FileManager::filter_extension($new_file_name)) {
  2012. Display :: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
  2013. } else {
  2014. if ($result) {
  2015. $comment = Database::escape_string($comment);
  2016. add_forum_attachment_file($comment, $last_post_id);
  2017. }
  2018. }
  2019. } else {
  2020. $message .= '<br />';
  2021. }
  2022. if ($current_forum['approval_direct_post'] == '1' && !api_is_allowed_to_edit(null, true)) {
  2023. $message .= get_lang('MessageHasToBeApproved').'<br />';
  2024. $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq(
  2025. ).'&amp;forum='.$values['forum_id'].'&amp;gidReq='.$_SESSION['toolgroup'].'&amp;origin='.$origin.'">'.get_lang(
  2026. 'Forum'
  2027. ).'</a><br />';
  2028. } else {
  2029. $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq(
  2030. ).'&amp;forum='.$values['forum_id'].'&amp;gidReq='.$_SESSION['toolgroup'].'&amp;origin='.$origin.'">'.get_lang(
  2031. 'Forum'
  2032. ).'</a><br />';
  2033. $message .= get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq(
  2034. ).'&amp;forum='.$values['forum_id'].'&amp;gidReq='.$_SESSION['toolgroup'].'&amp;origin='.$origin.'&amp;gradebook='.$gradebook.'&amp;thread='.$last_thread_id.'">'.get_lang(
  2035. 'Message'
  2036. ).'</a>';
  2037. }
  2038. $reply_info['new_post_id'] = $last_post_id;
  2039. $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
  2040. if ($my_post_notification == 1) {
  2041. set_notification('thread', $last_thread_id, true);
  2042. }
  2043. send_notification_mails($last_thread_id, $reply_info);
  2044. Session::erase('formelements');
  2045. Session::erase('origin');
  2046. Session::erase('breadcrumbs');
  2047. Session::erase('addedresource');
  2048. Session::erase('addedresourceid');
  2049. Display :: display_confirmation_message($message, false);
  2050. } else {
  2051. Display::display_error_message(get_lang('UplNoFileUploaded'));
  2052. }
  2053. }
  2054. /**
  2055. * This function displays the form that is used to add a post. This can be a new thread or a reply.
  2056. * @param $action is the parameter that determines if we are
  2057. * 1. newthread: adding a new thread (both empty) => No I-frame
  2058. * 2. replythread: Replying to a thread ($action = replythread) => I-frame with the complete thread (if enabled)
  2059. * 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)
  2060. * 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)
  2061. * @return void HMTL
  2062. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2063. * @version february 2006, dokeos 1.8
  2064. */
  2065. function show_add_post_form($action = '', $id = '', $form_values = '')
  2066. {
  2067. global $forum_setting;
  2068. global $current_forum;
  2069. global $_user;
  2070. global $origin;
  2071. $gradebook = Security::remove_XSS($_GET['gradebook']);
  2072. // Setting the class and text of the form title and submit button.
  2073. if ($_GET['action'] == 'quote') {
  2074. $class = 'save';
  2075. $text = get_lang('QuoteMessage');
  2076. } elseif ($_GET['action'] == 'replythread') {
  2077. $class = 'save';
  2078. $text = get_lang('ReplyToThread');
  2079. } elseif ($_GET['action'] == 'replymessage') {
  2080. $class = 'save';
  2081. $text = get_lang('ReplyToMessage');
  2082. } else {
  2083. $class = 'add';
  2084. $text = get_lang('CreateThread');
  2085. }
  2086. // Initialize the object.
  2087. $my_thread = isset($_GET['thread']) ? $_GET['thread'] : '';
  2088. $my_forum = isset($_GET['forum']) ? $_GET['forum'] : '';
  2089. $my_action = isset($_GET['action']) ? $_GET['action'] : '';
  2090. $my_post = isset($_GET['post']) ? $_GET['post'] : '';
  2091. $my_gradebook = isset($_GET['gradebook']) ? Security::remove_XSS($_GET['gradebook']) : '';
  2092. $form = new FormValidator('thread', 'post', api_get_self().'?forum='.Security::remove_XSS(
  2093. $my_forum
  2094. ).'&gradebook='.$gradebook.'&thread='.Security::remove_XSS($my_thread).'&post='.Security::remove_XSS(
  2095. $my_post
  2096. ).'&action='.Security::remove_XSS($my_action).'&origin='.$origin);
  2097. $form->setConstants(array('forum' => '5'));
  2098. $form->addElement('header', $text);
  2099. // Settting the form elements.
  2100. $form->addElement('hidden', 'forum_id', intval($my_forum));
  2101. $form->addElement('hidden', 'thread_id', intval($my_thread));
  2102. $form->addElement('hidden', 'gradebook', $my_gradebook);
  2103. // If anonymous posts are allowed we also display a form to allow the user to put his name or username in.
  2104. if ($current_forum['allow_anonymous'] == 1 && !isset($_user['user_id'])) {
  2105. $form->addElement('text', 'poster_name', get_lang('Name'));
  2106. $form->applyFilter('poster_name', 'html_filter');
  2107. }
  2108. $form->addElement('text', 'post_title', get_lang('Title'));
  2109. $form->addElement(
  2110. 'html_editor',
  2111. 'post_text',
  2112. get_lang('Text'),
  2113. true,
  2114. api_is_allowed_to_edit(null, true)
  2115. ? array('ToolbarSet' => 'Forum', 'Width' => '100%', 'Height' => '300')
  2116. : array('ToolbarSet' => 'ForumStudent', 'Width' => '100%', 'Height' => '300', 'UserStatus' => 'student')
  2117. );
  2118. $form->addRule('post_text', get_lang('ThisFieldIsRequired'), 'required');
  2119. $form->addElement(
  2120. 'advanced_settings',
  2121. '<a href="javascript://" onclick="return advanced_parameters()">
  2122. <span id="img_plus_and_minus">&nbsp;'.Display::return_icon(
  2123. 'div_show.gif',
  2124. get_lang('Show'),
  2125. array('style' => 'vertical-align:middle')
  2126. ).' '.get_lang('AdvancedParameters').'</span></a>'
  2127. );
  2128. $form->addElement('html', '<div id="id_qualify" style="display:none">');
  2129. if ((api_is_course_admin() || api_is_course_coach() || api_is_course_tutor()) && !($my_thread)) {
  2130. // Thread qualify
  2131. if (Gradebook::is_active()) {
  2132. //Loading gradebook select
  2133. load_gradebook_select_in_tool($form);
  2134. $form->addElement(
  2135. 'checkbox',
  2136. 'thread_qualify_gradebook',
  2137. '',
  2138. get_lang('QualifyThreadGradebook'),
  2139. 'onclick="javascript:if(this.checked==true){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
  2140. );
  2141. } else {
  2142. $form->addElement('hidden', 'thread_qualify_gradebook', false);
  2143. }
  2144. $form->addElement('html', '<div id="options_field" style="display:none">');
  2145. $form->addElement('text', 'numeric_calification', get_lang('QualificationNumeric'));
  2146. $form->applyFilter('numeric_calification', 'html_filter');
  2147. $form->addElement('text', 'calification_notebook_title', get_lang('TitleColumnGradebook'));
  2148. $form->applyFilter('calification_notebook_title', 'html_filter');
  2149. $form->addElement(
  2150. 'text',
  2151. 'weight_calification',
  2152. get_lang('QualifyWeight'),
  2153. 'value="0.00" Style="width:40px" onfocus="javascript: this.select();"'
  2154. );
  2155. $form->applyFilter('weight_calification', 'html_filter');
  2156. $form->addElement('html', '</div>');
  2157. }
  2158. if ($forum_setting['allow_post_notification'] && isset($_user['user_id'])) {
  2159. $form->addElement('checkbox', 'post_notification', '', get_lang('NotifyByEmail').' ('.$_user['mail'].')');
  2160. }
  2161. if ($forum_setting['allow_sticky'] && api_is_allowed_to_edit(null, true) && $action == 'newthread') {
  2162. $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
  2163. }
  2164. if ($current_forum['allow_attachments'] == '1' || api_is_allowed_to_edit(null, true)) {
  2165. $values = $form->exportValues();
  2166. }
  2167. // User upload
  2168. $form->addElement('static', null, null, get_lang('AddAnAttachment'));
  2169. $form->addElement('file', 'user_upload', get_lang('FileName'), '');
  2170. $form->addElement('textarea', 'file_comment', get_lang('FileComment'), array('rows' => 4, 'cols' => 34));
  2171. $form->applyFilter('file_comment', 'html_filter');
  2172. $form->addElement('html', '</div>');
  2173. $form->addElement('style_submit_button', 'SubmitPost', $text, 'class="'.$class.'"');
  2174. $form->add_real_progress_bar('DocumentUpload', 'user_upload');
  2175. if (!empty($form_values)) {
  2176. $defaults['post_title'] = prepare4display($form_values['post_title']);
  2177. $defaults['post_text'] = prepare4display($form_values['post_text']);
  2178. $defaults['post_notification'] = strval(intval($form_values['post_notification']));
  2179. $defaults['thread_sticky'] = strval(intval($form_values['thread_sticky']));
  2180. }
  2181. // If we are quoting a message we have to retrieve the information of the post we are quoting so that
  2182. // we can add this as default to the textarea.
  2183. if (($action == 'quote' || $action == 'replymessage') && isset($my_post)) {
  2184. // 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 !!!)
  2185. $form->addElement('hidden', 'post_parent_id', strval(intval($my_post))); // Note: This has to be cleaned first.
  2186. // If we are replying or are quoting then we display a default title.
  2187. $values = get_post_information($my_post); // Note: This has to be cleaned first.
  2188. $defaults['post_title'] = get_lang('ReplyShort').api_html_entity_decode($values['post_title'], ENT_QUOTES);
  2189. // When we are quoting a message then we have to put that message into the wysiwyg editor.
  2190. // Note: The style has to be hardcoded here because using class="quote" didn't work.
  2191. if ($action == 'quote') {
  2192. $defaults['post_text'] = '<div>&nbsp;</div><div style="margin: 5px;"><div style="font-size: 90%; font-style: italic;">'.get_lang(
  2193. 'Quoting'
  2194. ).' '.api_get_person_name(
  2195. $values['firstname'],
  2196. $values['lastname']
  2197. ).':</div><div style="color: #006600; font-size: 90%; font-style: italic; background-color: #FAFAFA; border: #D1D7DC 1px solid; padding: 3px;">'.prepare4display(
  2198. $values['post_text']
  2199. ).'</div></div><div>&nbsp;</div><div>&nbsp;</div>';
  2200. }
  2201. }
  2202. $form->setDefaults(isset($defaults) ? $defaults : null);
  2203. // The course admin can make a thread sticky (=appears with special icon and always on top).
  2204. $form->addRule('post_title', get_lang('ThisFieldIsRequired'), 'required');
  2205. if ($current_forum['allow_anonymous'] == 1 && !isset($_user['user_id'])) {
  2206. $form->addRule('poster_name', get_lang('ThisFieldIsRequired'), 'required');
  2207. }
  2208. // Validation or display
  2209. if ($form->validate()) {
  2210. $check = Security::check_token('post');
  2211. if ($check) {
  2212. $values = $form->exportValues();
  2213. if ($values['thread_qualify_gradebook'] == '1' && empty($values['weight_calification'])) {
  2214. Display::display_error_message(
  2215. get_lang('YouMustAssignWeightOfQualification').'&nbsp;<a href="javascript:window.back()">'.get_lang(
  2216. 'Back'
  2217. ).'</a>',
  2218. false
  2219. );
  2220. return false;
  2221. }
  2222. Security::clear_token();
  2223. return $values;
  2224. }
  2225. } else {
  2226. $token = Security::get_token();
  2227. $form->addElement('hidden', 'sec_token');
  2228. $form->setConstants(array('sec_token' => $token));
  2229. $iframe = null;
  2230. if ($forum_setting['show_thread_iframe_on_reply'] && $action != 'newthread') {
  2231. $iframe = "<iframe style=\"border: 1px solid black\" src=\"iframe_thread.php?forum=".Security::remove_XSS(
  2232. $my_forum
  2233. )."&amp;thread=".Security::remove_XSS($my_thread)."#".Security::remove_XSS(
  2234. $my_post
  2235. )."\" width=\"100%\"></iframe>";
  2236. }
  2237. if (!empty($iframe)) {
  2238. $form->addElement('label', get_lang('Thread'), $iframe);
  2239. }
  2240. $form->display();
  2241. }
  2242. }
  2243. /**
  2244. * @param integer contains the information of user id
  2245. * @param integer contains the information of thread id
  2246. * @param integer contains the information of thread qualify
  2247. * @param integer contains the information of user id of qualifier
  2248. * @param integer contains the information of time
  2249. * @param integer contains the information of session id
  2250. * @return Array() optional
  2251. * @author Isaac Flores <isaac.flores@dokeos.com>, U.N.A.S University
  2252. * @version October 2008, dokeos 1.8.6
  2253. */
  2254. function store_theme_qualify(
  2255. $user_id,
  2256. $thread_id,
  2257. $thread_qualify = 0,
  2258. $qualify_user_id = 0,
  2259. $qualify_time,
  2260. $session_id = null
  2261. ) {
  2262. $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
  2263. $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
  2264. $course_id = api_get_course_int_id();
  2265. if ($user_id == strval(intval($user_id)) && $thread_id == strval(intval($thread_id)) && $thread_qualify == strval(
  2266. floatval($thread_qualify)
  2267. )
  2268. ) {
  2269. // Testing
  2270. $sql_string = "SELECT thread_qualify_max FROM ".$table_threads." WHERE c_id = $course_id AND thread_id=".$thread_id.";";
  2271. $res_string = Database::query($sql_string);
  2272. $row_string = Database::fetch_array($res_string);
  2273. if ($thread_qualify <= $row_string[0]) {
  2274. $sql1 = "SELECT COUNT(*) FROM ".$table_threads_qualify." WHERE c_id = $course_id AND user_id=".$user_id." and thread_id=".$thread_id.";";
  2275. $res1 = Database::query($sql1);
  2276. $row = Database::fetch_array($res1);
  2277. if ($row[0] == 0) {
  2278. $sql = "INSERT INTO $table_threads_qualify (c_id, user_id, thread_id,qualify,qualify_user_id,qualify_time,session_id)
  2279. VALUES (".$course_id.", '".$user_id."','".$thread_id."',".(float)$thread_qualify.", '".$qualify_user_id."','".$qualify_time."','".$session_id."')";
  2280. $res = Database::query($sql);
  2281. return $res;
  2282. } else {
  2283. $sql1 = "SELECT qualify FROM ".$table_threads_qualify." WHERE c_id = $course_id AND user_id=".$user_id." and thread_id=".$thread_id.";";
  2284. $rs = Database::query($sql1);
  2285. $row = Database::fetch_array($rs);
  2286. $row[1] = "update";
  2287. return $row;
  2288. }
  2289. } else {
  2290. return null;
  2291. }
  2292. }
  2293. }
  2294. /**
  2295. * This function shows qualify.
  2296. * @param string contains the information of option to run
  2297. * @param string contains the information the current course id
  2298. * @param integer contains the information the current forum id
  2299. * @param integer contains the information the current user id
  2300. * @param integer contains the information the current thread id
  2301. * @return integer qualify
  2302. * <code> $option=1 obtained the qualification of the current thread</code>
  2303. * @author Isaac Flores <isaac.flores@dokeos.com>, U.N.A.S University
  2304. * @version October 2008, dokeos 1.8.6
  2305. */
  2306. function show_qualify($option, $user_id, $thread_id)
  2307. {
  2308. $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
  2309. $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
  2310. $course_id = api_get_course_int_id();
  2311. $user_id = intval($user_id);
  2312. $thread_id = intval($thread_id);
  2313. if (empty($user_id) || empty($thread_id)) {
  2314. return false;
  2315. }
  2316. switch ($option) {
  2317. case 1:
  2318. $sql = "SELECT qualify FROM ".$table_threads_qualify." WHERE c_id = $course_id AND user_id=".$user_id." and thread_id=".$thread_id;
  2319. break;
  2320. case 2:
  2321. $sql = "SELECT thread_qualify_max FROM ".$table_threads." WHERE c_id = $course_id AND thread_id=".$thread_id.";";
  2322. break;
  2323. }
  2324. $rs = Database::query($sql);
  2325. $row = Database::fetch_array($rs);
  2326. return $row[0];
  2327. }
  2328. /**
  2329. * This function gets qualify historical.
  2330. * @param integer contains the information the current user id
  2331. * @param integer contains the information the current thread id
  2332. * @param boolean contains the information of option to run
  2333. * @return array()
  2334. * @author Christian Fasanando <christian.fasanando@dokeos.com>,
  2335. * @author Isaac Flores <isaac.flores@dokeos.com>,
  2336. * @version October 2008, dokeos 1.8.6
  2337. */
  2338. function get_historical_qualify($user_id, $thread_id, $opt)
  2339. {
  2340. $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
  2341. $course_id = api_get_course_int_id();
  2342. $my_qualify_log = array();
  2343. if ($opt == 'false') {
  2344. $sql = "SELECT * FROM ".$table_threads_qualify_log." WHERE c_id = $course_id AND thread_id='".Database::escape_string(
  2345. $thread_id
  2346. )."' and user_id='".Database::escape_string($user_id)."' ORDER BY qualify_time";
  2347. } else {
  2348. $sql = "SELECT * FROM ".$table_threads_qualify_log." WHERE c_id = $course_id AND thread_id='".Database::escape_string(
  2349. $thread_id
  2350. )."' and user_id='".Database::escape_string($user_id)."' ORDER BY qualify_time DESC";
  2351. }
  2352. $rs = Database::query($sql);
  2353. while ($row = Database::fetch_array($rs, 'ASSOC')) {
  2354. $my_qualify_log[] = $row;
  2355. }
  2356. return $my_qualify_log;
  2357. }
  2358. /**
  2359. * This function stores qualify historical.
  2360. * @param boolean contains the information of option to run
  2361. * @param string contains the information the current course id
  2362. * @param integer contains the information the current forum id
  2363. * @param integer contains the information the current user id
  2364. * @param integer contains the information the current thread id
  2365. * @param integer contains the information the current qualify
  2366. * @return void
  2367. * <code>$option=1 obtained the qualification of the current thread</code>
  2368. * @author Isaac Flores <isaac.flores@dokeos.com>, U.N.A.S University
  2369. * @version October 2008, dokeos 1.8.6
  2370. */
  2371. function store_qualify_historical(
  2372. $option,
  2373. $couser_id,
  2374. $forum_id,
  2375. $user_id,
  2376. $thread_id,
  2377. $current_qualify,
  2378. $qualify_user_id
  2379. ) {
  2380. $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
  2381. $table_threads = Database::get_course_table(TABLE_FORUM_THREAD);
  2382. $table_threads_qualify_log = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY_LOG);
  2383. $current_date = date('Y-m-d H:i:s');
  2384. $course_id = api_get_course_int_id();
  2385. if ($user_id == strval(intval($user_id)) && $thread_id == strval(intval($thread_id)) && $option == 1) {
  2386. // Extract information of thread_qualify.
  2387. $sql = "SELECT qualify,qualify_time FROM ".$table_threads_qualify." WHERE c_id = $course_id AND user_id=".$user_id." and thread_id=".$thread_id.";";
  2388. $rs = Database::query($sql);
  2389. $row = Database::fetch_array($rs);
  2390. // Insert thread_historical.
  2391. $sql1 = "INSERT INTO $table_threads_qualify_log (c_id, user_id, thread_id,qualify,qualify_user_id,qualify_time,session_id)
  2392. VALUES(".$course_id.", '".$user_id."','".$thread_id."',".(float)$row[0].", '".$qualify_user_id."','".$row[1]."','')";
  2393. Database::query($sql1);
  2394. // Update
  2395. $sql2 = "UPDATE ".$table_threads_qualify." SET qualify=".$current_qualify.",qualify_time='".$current_date."' WHERE c_id = $course_id AND user_id=".$user_id." and thread_id=".$thread_id.";";
  2396. Database::query($sql2);
  2397. }
  2398. }
  2399. /**
  2400. * This function shows current thread qualify .
  2401. * @param integer contains the information the current thread id
  2402. * @param integer contains the information the current session id
  2403. * @return array or null if is empty
  2404. * @author Isaac Flores <isaac.flores@dokeos.com>, U.N.A.S University
  2405. * @version December 2008, dokeos 1.8.6
  2406. */
  2407. function current_qualify_of_thread($thread_id, $session_id)
  2408. {
  2409. $table_threads_qualify = Database::get_course_table(TABLE_FORUM_THREAD_QUALIFY);
  2410. $course_id = api_get_course_int_id();
  2411. $res = Database::query(
  2412. "SELECT qualify FROM $table_threads_qualify WHERE c_id = $course_id AND thread_id = $thread_id AND session_id = $session_id"
  2413. );
  2414. $row = Database::fetch_array($res, 'ASSOC');
  2415. return $row['qualify'];
  2416. }
  2417. /**
  2418. * This function stores a reply in the forum_post table.
  2419. * It also updates the forum_threads table (thread_replies +1 , thread_last_post, thread_date)
  2420. *
  2421. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2422. * @version february 2006, dokeos 1.8
  2423. */
  2424. function store_reply($values)
  2425. {
  2426. $_course = api_get_course_info();
  2427. global $current_forum;
  2428. global $origin;
  2429. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  2430. $forum_table_attachment = Database :: get_course_table(TABLE_FORUM_ATTACHMENT);
  2431. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  2432. $gradebook = Security::remove_XSS($_GET['gradebook']);
  2433. $post_date = api_get_utc_datetime();
  2434. if ($current_forum['approval_direct_post'] == '1' && !api_is_allowed_to_edit(null, true)) {
  2435. $visible = 0; // The post has not been approved yet.
  2436. } else {
  2437. $visible = 1;
  2438. }
  2439. $upload_ok = 1;
  2440. $has_attachment = false;
  2441. if (!empty($_FILES['user_upload']['name'])) {
  2442. $upload_ok = FileManager::process_uploaded_file($_FILES['user_upload']);
  2443. $has_attachment = true;
  2444. }
  2445. $return = array();
  2446. if ($upload_ok) {
  2447. // We first store an entry in the forum_post table.
  2448. $sql = "INSERT INTO $table_posts (c_id, post_title, post_text, thread_id, forum_id, poster_id, post_date, post_notification, post_parent_id, visible)
  2449. VALUES (
  2450. ".api_get_course_int_id().",
  2451. '".Database::escape_string($values['post_title'])."',
  2452. '".Database::escape_string(isset($values['post_text']) ? ($values['post_text']) : null)."',
  2453. '".Database::escape_string($values['thread_id'])."',
  2454. '".Database::escape_string($values['forum_id'])."',
  2455. '".api_get_user_id()."',
  2456. '".$post_date."',
  2457. '".Database::escape_string(
  2458. isset($values['post_notification']) ? $values['post_notification'] : null
  2459. )."',
  2460. '".Database::escape_string(isset($values['post_parent_id']) ? $values['post_parent_id'] : null)."',
  2461. '".Database::escape_string($visible)."')";
  2462. $result = Database::query($sql);
  2463. $new_post_id = Database::insert_id();
  2464. $values['new_post_id'] = $new_post_id;
  2465. $message = get_lang('ReplyAdded');
  2466. if ($has_attachment) {
  2467. $course_dir = $_course['path'].'/upload/forum';
  2468. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  2469. $updir = $sys_course_path.$course_dir;
  2470. // Try to add an extension to the file if it hasn't one.
  2471. $new_file_name = FileManager::add_ext_on_mime(
  2472. stripslashes($_FILES['user_upload']['name']),
  2473. $_FILES['user_upload']['type']
  2474. );
  2475. // User's file name
  2476. $file_name = $_FILES['user_upload']['name'];
  2477. if (!FileManager::filter_extension($new_file_name)) {
  2478. $return['msg'] = get_lang('UplUnableToSaveFileFilteredExtension');
  2479. $return['type'] = 'error';
  2480. } else {
  2481. $new_file_name = uniqid('');
  2482. $new_path = $updir.'/'.$new_file_name;
  2483. $result = @move_uploaded_file($_FILES['user_upload']['tmp_name'], $new_path);
  2484. $comment = $values['file_comment'];
  2485. // Storing the attachments if any.
  2486. if ($result) {
  2487. $sql = 'INSERT INTO '.$forum_table_attachment.'(c_id, filename,comment, path, post_id,size) '.
  2488. "VALUES (".api_get_course_int_id().", '".Database::escape_string(
  2489. $file_name
  2490. )."', '".Database::escape_string($comment)."', '".Database::escape_string(
  2491. $new_file_name
  2492. )."' , '".$new_post_id."', '".intval($_FILES['user_upload']['size'])."' )";
  2493. $result = Database::query($sql);
  2494. $message .= ' / '.get_lang('FileUploadSucces');
  2495. $last_id = Database::insert_id();
  2496. api_item_property_update(
  2497. $_course,
  2498. TOOL_FORUM_ATTACH,
  2499. $last_id,
  2500. 'ForumAttachmentAdded',
  2501. api_get_user_id()
  2502. );
  2503. }
  2504. }
  2505. }
  2506. // Update the thread.
  2507. update_thread($values['thread_id'], $new_post_id, $post_date);
  2508. // Update the forum.
  2509. api_item_property_update($_course, TOOL_FORUM, $values['forum_id'], 'NewMessageInForum', api_get_user_id());
  2510. if ($current_forum['approval_direct_post'] == '1' && !api_is_allowed_to_edit(null, true)) {
  2511. $message .= '<br />'.get_lang('MessageHasToBeApproved').'<br />';
  2512. }
  2513. //$message .= '<br />'.get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&amp;forum='.$values['forum_id'].'&amp;gidReq='.$_SESSION['toolgroup'].'&amp;origin='.$origin.'">'.get_lang('Forum').'</a><br />';
  2514. //$message .= get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&amp;forum='.$values['forum_id'].'&amp;thread='.$values['thread_id'].'&amp;gidReq='.$_SESSION['toolgroup'].'&amp;origin='.$origin.'&amp;gradebook='.$gradebook.'">'.get_lang('Message').'</a>';
  2515. // Setting the notification correctly.
  2516. $my_post_notification = isset($values['post_notification']) ? $values['post_notification'] : null;
  2517. if ($my_post_notification == 1) {
  2518. set_notification('thread', $values['thread_id'], true);
  2519. }
  2520. send_notification_mails($values['thread_id'], $values);
  2521. Session::erase('formelements');
  2522. Session::erase('origin');
  2523. Session::erase('breadcrumbs');
  2524. Session::erase('addedresource');
  2525. Session::erase('addedresourceid');
  2526. $return['msg'] = $message;
  2527. $return['type'] = 'confirmation';
  2528. } else {
  2529. $return['msg'] = get_lang('UplNoFileUploaded').' '.get_lang('UplSelectFileFirst');
  2530. $return['type'] = 'error';
  2531. }
  2532. return $return;
  2533. }
  2534. /**
  2535. * This function displays the form that is used to edit a post. This can be a new thread or a reply.
  2536. * @param array contains all the information about the current post
  2537. * @param array contains all the information about the current thread
  2538. * @param array contains all info about the current forum (to check if attachments are allowed)
  2539. * @param array contains the default values to fill the form
  2540. * @return void
  2541. *
  2542. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2543. * @version february 2006, dokeos 1.8
  2544. */
  2545. function show_edit_post_form($current_post, $current_thread, $current_forum, $form_values = '', $id_attach = 0)
  2546. {
  2547. global $forum_setting;
  2548. global $origin;
  2549. $gradebook = Security::remove_XSS($_GET['gradebook']);
  2550. // Initialize the object.
  2551. $form = new FormValidator('edit_post', 'post', api_get_self().'?forum='.Security::remove_XSS(
  2552. $_GET['forum']
  2553. ).'&amp;gradebook='.$gradebook.'&amp;origin='.$origin.'&amp;thread='.Security::remove_XSS(
  2554. $_GET['thread']
  2555. ).'&amp;post='.Security::remove_XSS($_GET['post']));
  2556. $form->addElement('header', get_lang('EditPost'));
  2557. // Settting the form elements.
  2558. $form->addElement('hidden', 'post_id', $current_post['post_id']);
  2559. $form->addElement('hidden', 'thread_id', $current_thread['thread_id']);
  2560. $form->addElement('hidden', 'id_attach', $id_attach);
  2561. if ($current_post['post_parent_id'] == 0) {
  2562. $form->addElement('hidden', 'is_first_post_of_thread', '1');
  2563. }
  2564. $form->addElement('text', 'post_title', get_lang('Title'), 'class="input_titles"');
  2565. $form->applyFilter('post_title', 'html_filter');
  2566. $form->addElement(
  2567. 'html_editor',
  2568. 'post_text',
  2569. get_lang('Text'),
  2570. null,
  2571. api_is_allowed_to_edit(null, true)
  2572. ? array('ToolbarSet' => 'Forum', 'Width' => '100%', 'Height' => '400')
  2573. : array('ToolbarSet' => 'ForumStudent', 'Width' => '100%', 'Height' => '400', 'UserStatus' => 'student')
  2574. );
  2575. $form->addRule('post_text', get_lang('ThisFieldIsRequired'), 'required');
  2576. $form->addElement(
  2577. 'advanced_settings',
  2578. '<a href="javascript://" onclick="return advanced_parameters()"><span id="img_plus_and_minus">'.Display::return_icon(
  2579. 'div_show.gif',
  2580. get_lang('Show'),
  2581. array('style' => 'vertical-align:middle')
  2582. ).''.get_lang('AdvancedParameters').'</span></a>'
  2583. );
  2584. $form->addElement('html', '<div id="id_qualify" style="display:none">');
  2585. if (!isset($_GET['edit'])) {
  2586. if (Gradebook::is_active()) {
  2587. $form->addElement('label', '<strong>'.get_lang('AlterQualifyThread').'</strong>');
  2588. $form->addElement(
  2589. 'checkbox',
  2590. 'thread_qualify_gradebook',
  2591. '',
  2592. get_lang('QualifyThreadGradebook'),
  2593. 'onclick="javascript: if(this.checked){document.getElementById(\'options_field\').style.display = \'block\';}else{document.getElementById(\'options_field\').style.display = \'none\';}"'
  2594. );
  2595. $link_info = is_resource_in_course_gradebook(api_get_course_id(), 5, $_GET['thread'], api_get_session_id());
  2596. if (!empty($link_info)) {
  2597. $defaults['thread_qualify_gradebook'] = true;
  2598. $defaults['category_id'] = $link_info['category_id'];
  2599. } else {
  2600. $defaults['thread_qualify_gradebook'] = false;
  2601. $defaults['category_id'] = '';
  2602. }
  2603. } else {
  2604. $form->addElement('hidden', 'thread_qualify_gradebook', false);
  2605. $defaults['thread_qualify_gradebook'] = false;
  2606. }
  2607. if (!empty($defaults['thread_qualify_gradebook'])) {
  2608. $form->addElement('html', '<div id="options_field" style="display:block">');
  2609. } else {
  2610. $form->addElement('html', '<div id="options_field" style="display:none">');
  2611. }
  2612. //Loading gradebook select
  2613. load_gradebook_select_in_tool($form);
  2614. $form->addElement(
  2615. 'text',
  2616. 'numeric_calification',
  2617. get_lang('QualificationNumeric'),
  2618. 'value="'.$current_thread['thread_qualify_max'].'" style="width:40px"'
  2619. );
  2620. $form->applyFilter('numeric_calification', 'html_filter');
  2621. $form->addElement(
  2622. 'text',
  2623. 'calification_notebook_title',
  2624. get_lang('TitleColumnGradebook'),
  2625. 'value="'.$current_thread['thread_title_qualify'].'"'
  2626. );
  2627. $form->applyFilter('calification_notebook_title', 'html_filter');
  2628. $form->addElement(
  2629. 'text',
  2630. 'weight_calification',
  2631. array(get_lang('QualifyWeight'), null, ''),
  2632. 'value="'.$current_thread['thread_weight'].'" style="width:40px"'
  2633. );
  2634. $form->applyFilter('weight_calification', 'html_filter');
  2635. $form->addElement('html', '</div>');
  2636. }
  2637. if ($forum_setting['allow_post_notification']) {
  2638. $form->addElement(
  2639. 'checkbox',
  2640. 'post_notification',
  2641. '',
  2642. get_lang('NotifyByEmail').' ('.$current_post['email'].')'
  2643. );
  2644. }
  2645. if ($forum_setting['allow_sticky'] && api_is_allowed_to_edit(
  2646. null,
  2647. true
  2648. ) && $current_post['post_parent_id'] == 0
  2649. ) { // The sticky checkbox only appears when it is the first post of a thread.
  2650. $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
  2651. if ($current_thread['thread_sticky'] == 1) {
  2652. $defaults['thread_sticky'] = true;
  2653. }
  2654. }
  2655. $attachment_list = get_attachment($current_post['post_id']);
  2656. $message = get_lang('AddAnAttachment');
  2657. if (!empty($attachment_list)) {
  2658. //$message = ;
  2659. $form->addElement(
  2660. 'label',
  2661. get_lang('EditAnAttachment'),
  2662. Display::return_icon(
  2663. 'attachment.gif',
  2664. get_lang('Attachment')
  2665. ).'&nbsp;'.$attachment_list['filename'].(!empty($attachment_list['comment']) ? '('.$attachment_list['comment'].')' : '')
  2666. );
  2667. $form->addElement('checkbox', 'remove_attach', null, get_lang('DeleteAttachmentFile'));
  2668. } else {
  2669. // User upload
  2670. $form->addElement('label', $message);
  2671. $form->addElement('file', 'user_upload', get_lang('FileName'), '');
  2672. $form->addElement('textarea', 'file_comment', get_lang('FileComment'), array('rows' => 4, 'cols' => 34));
  2673. $form->applyFilter('file_comment', 'html_filter');
  2674. }
  2675. if ($current_forum['allow_attachments'] == '1' || api_is_allowed_to_edit(null, true)) {
  2676. if (empty($form_values) && !isset($_POST['SubmitPost'])) {
  2677. //edit_added_resources('forum_post', $current_post['post_id']);
  2678. }
  2679. }
  2680. $form->addElement('html', '</div>');
  2681. $form->addElement('style_submit_button', 'SubmitPost', get_lang('ModifyThread'), 'class="save"');
  2682. // Setting the default values for the form elements.
  2683. $defaults['post_title'] = $current_post['post_title'];
  2684. $defaults['post_text'] = $current_post['post_text'];
  2685. if ($current_post['post_notification'] == 1) {
  2686. $defaults['post_notification'] = true;
  2687. }
  2688. if (!empty($form_values)) {
  2689. $defaults['post_notification'] = Security::remove_XSS($form_values['post_notification']);
  2690. $defaults['thread_sticky'] = Security::remove_XSS($form_values['thread_sticky']);
  2691. }
  2692. $form->setDefaults($defaults);
  2693. // The course admin can make a thread sticky (=appears with special icon and always on top).
  2694. $form->addRule('post_title', get_lang('ThisFieldIsRequired'), 'required');
  2695. // Validation or display
  2696. if ($form->validate()) {
  2697. $values = $form->exportValues();
  2698. if ($values['thread_qualify_gradebook'] == '1' && empty($values['weight_calification'])) {
  2699. Display::display_error_message(
  2700. get_lang('YouMustAssignWeightOfQualification').'&nbsp;<a href="javascript:window.back()">'.get_lang(
  2701. 'Back'
  2702. ).'</a>',
  2703. false
  2704. );
  2705. return false;
  2706. }
  2707. return $values;
  2708. } else {
  2709. $form->display();
  2710. }
  2711. }
  2712. /**
  2713. * This function stores the edit of a post in the forum_post table.
  2714. *
  2715. * @param array
  2716. * @return void HTML
  2717. *
  2718. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2719. * @version february 2006, dokeos 1.8
  2720. */
  2721. function store_edit_post($values)
  2722. {
  2723. global $origin;
  2724. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  2725. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  2726. $gradebook = Security::remove_XSS($_GET['gradebook']);
  2727. $course_id = api_get_course_int_id();
  2728. // First we check if the change affects the thread and if so we commit the changes (sticky and post_title=thread_title are relevant).
  2729. //if (array_key_exists('is_first_post_of_thread',$values) AND $values['is_first_post_of_thread']=='1') {
  2730. $posts = get_posts($values['thread_id']);
  2731. $first_post = null;
  2732. if (!empty($posts)) {
  2733. $first_post = $posts[0];
  2734. }
  2735. if (!empty($first_post) && $first_post['post_id'] == $values['post_id']) {
  2736. $sql = "UPDATE $table_threads SET
  2737. thread_title ='".Database::escape_string($values['post_title'])."',
  2738. thread_sticky ='".Database::escape_string(isset($values['thread_sticky']) ? $values['thread_sticky'] : null)."'," .
  2739. "thread_title_qualify ='".Database::escape_string($values['calification_notebook_title'])."',".
  2740. "thread_qualify_max ='".Database::escape_string($values['numeric_calification'])."',".
  2741. "thread_weight ='".Database::escape_string($values['weight_calification'])."'".
  2742. " WHERE c_id = $course_id AND thread_id='".intval($values['thread_id'])."'";
  2743. Database::query($sql);
  2744. }
  2745. //}
  2746. // Update the post_title and the post_text.
  2747. $sql = "UPDATE $table_posts SET
  2748. post_title ='".Database::escape_string($values['post_title'])."',
  2749. post_text ='".Database::escape_string($values['post_text'])."',
  2750. post_notification ='".Database::escape_string(isset($values['post_notification'])?$values['post_notification']:null)."'
  2751. WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
  2752. Database::query($sql);
  2753. if (!empty($values['remove_attach'])) {
  2754. delete_attachment($values['post_id']);
  2755. }
  2756. if (empty($values['id_attach'])) {
  2757. add_forum_attachment_file($values['file_comment'], $values['post_id']);
  2758. } else {
  2759. edit_forum_attachment_file($values['file_comment'], $values['post_id'], $values['id_attach']);
  2760. }
  2761. if (api_is_course_admin() == true) {
  2762. $ccode = api_get_course_id();
  2763. $sid = api_get_session_id();
  2764. $link_info = is_resource_in_course_gradebook($ccode, 5, $values['thread_id'], $sid);
  2765. $link_id = $link_info['id'];
  2766. $thread_qualify_gradebook = isset($values['thread_qualify_gradebook']) ? $values['thread_qualify_gradebook'] : null;
  2767. if ($thread_qualify_gradebook != 1) {
  2768. if ($link_info !== false) {
  2769. remove_resource_from_course_gradebook($link_id);
  2770. }
  2771. } else {
  2772. if ($link_info === false && !$_GET['thread']) {
  2773. $weigthqualify = $values['weight_calification'];
  2774. add_resource_to_course_gradebook(
  2775. $values['category_id'],
  2776. $ccode,
  2777. 5,
  2778. $values['thread_id'],
  2779. Database::escape_string(stripslashes($values['calification_notebook_title'])),
  2780. $weigthqualify,
  2781. $values['numeric_calification'],
  2782. null,
  2783. 0,
  2784. $sid
  2785. );
  2786. }
  2787. }
  2788. }
  2789. // Storing the attachments if any.
  2790. //update_added_resources('forum_post', $values['post_id']);
  2791. $message = get_lang('EditPostStored').'<br />';
  2792. $message .= get_lang('ReturnTo').' <a href="viewforum.php?'.api_get_cidreq().'&amp;forum='.Security::remove_XSS(
  2793. $_GET['forum']
  2794. ).'&amp;gidReq='.$_SESSION['toolgroup'].'&amp;origin='.$origin.'">'.get_lang('Forum').'</a><br />';
  2795. $message .= get_lang('ReturnTo').' <a href="viewthread.php?'.api_get_cidreq().'&amp;forum='.Security::remove_XSS(
  2796. $_GET['forum']
  2797. ).'&amp;gidReq='.$_SESSION['toolgroup'].'&amp;origin='.$origin.'&amp;gradebook='.$gradebook.'&amp;thread='.$values['thread_id'].'&amp;post='.Security::remove_XSS(
  2798. $_GET['post']
  2799. ).'">'.get_lang('Message').'</a>';
  2800. Session::erase('formelements');
  2801. Session::erase('origin');
  2802. Session::erase('breadcrumbs');
  2803. Session::erase('addedresource');
  2804. Session::erase('addedresourceid');
  2805. Display :: display_confirmation_message($message, false);
  2806. }
  2807. /**
  2808. * This function displays the firstname and lastname of the user as a link to the user tool.
  2809. *
  2810. * @param string names
  2811. * @ in_title : title tootip
  2812. * @return string HTML
  2813. *
  2814. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2815. * @version february 2006, dokeos 1.8
  2816. */
  2817. function display_user_link($user_id, $name, $origin = '', $in_title = '')
  2818. {
  2819. if ($user_id != 0) {
  2820. return '<a title="'.api_htmlentities(
  2821. $in_title,
  2822. ENT_QUOTES
  2823. ).'" href="../user/userInfo.php?uInfo='.$user_id.'" '.(!empty($origin) ? 'target="_self"' : '').'>'.$name.'</a>';
  2824. } else {
  2825. return $name.' ('.get_lang('Anonymous').')';
  2826. }
  2827. }
  2828. /**
  2829. * This function displays the user image from the profile, with a link to the user's details.
  2830. * @param int User's database ID
  2831. * @param str User's name
  2832. * @return string An HTML with the anchor and the image of the user
  2833. * @author Julio Montoya <gugli100@gmail.com>
  2834. */
  2835. function display_user_image($user_id, $name, $origin = '')
  2836. {
  2837. $link = '<a href="../user/userInfo.php?uInfo='.$user_id.'" '.(!empty($origin) ? 'target="_self"' : '').'>';
  2838. $attrb = array();
  2839. if ($user_id != 0) {
  2840. $image_path = UserManager::get_user_picture_path_by_id($user_id, 'web', false, true);
  2841. $image_repository = $image_path['dir'];
  2842. $existing_image = $image_path['file'];
  2843. $friends_profile = UserManager::get_picture_user(
  2844. $user_id,
  2845. $image_path['file'],
  2846. 0,
  2847. USER_IMAGE_SIZE_MEDIUM,
  2848. 'width="96" height="96" '
  2849. );
  2850. return $link.'<img src="'.$friends_profile['file'].'" '.$friends_profile['style'].' alt="'.$name.'" title="'.$name.'" /></a>';
  2851. } else {
  2852. return $link.'<img src="'.api_get_path(
  2853. WEB_CODE_PATH
  2854. )."img/unknown.jpg".'" alt="'.$name.'" title="'.$name.'" /></a>';
  2855. }
  2856. }
  2857. /**
  2858. * The thread view counter gets increased every time someone looks at the thread
  2859. *
  2860. * @param int
  2861. * @return void
  2862. *
  2863. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2864. * @version february 2006, dokeos 1.8
  2865. */
  2866. function increase_thread_view($thread_id)
  2867. {
  2868. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  2869. $course_id = api_get_course_int_id();
  2870. $sql = "UPDATE $table_threads SET thread_views=thread_views+1
  2871. WHERE c_id = $course_id AND thread_id='".Database::escape_string(
  2872. $thread_id
  2873. )."'"; // This needs to be cleaned first.
  2874. $result = Database::query($sql);
  2875. }
  2876. /**
  2877. * The relies counter gets increased every time somebody replies to the thread
  2878. *
  2879. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2880. * @version february 2006, dokeos 1.8
  2881. */
  2882. function update_thread($thread_id, $last_post_id, $post_date)
  2883. {
  2884. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  2885. $course_id = api_get_course_int_id();
  2886. $sql = "UPDATE $table_threads SET thread_replies=thread_replies+1,
  2887. thread_last_post='".Database::escape_string($last_post_id)."',
  2888. thread_date='".Database::escape_string($post_date)."'
  2889. WHERE c_id = $course_id AND thread_id='".Database::escape_string(
  2890. $thread_id
  2891. )."'"; // this needs to be cleaned first
  2892. $result = Database::query($sql);
  2893. }
  2894. /**
  2895. * This function is called when the user is not allowed in this forum/thread/...
  2896. * @return bool display message of "not allowed"
  2897. *
  2898. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2899. * @version february 2006, dokeos 1.8
  2900. */
  2901. function forum_not_allowed_here()
  2902. {
  2903. Display :: display_error_message(get_lang('NotAllowedHere'));
  2904. Display :: display_footer();
  2905. return false;
  2906. }
  2907. /**
  2908. * This function is used to find all the information about what's new in the forum tool
  2909. * @return void
  2910. *
  2911. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2912. * @version february 2006, dokeos 1.8
  2913. */
  2914. function get_whats_new()
  2915. {
  2916. global $_user;
  2917. $_course = api_get_course_info();
  2918. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  2919. $tracking_last_tool_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
  2920. // Note: This has to be replaced by the tool constant later. But temporarily bb_forum is used since this is the only thing that is in the tracking currently.
  2921. //$tool = TOOL_FORUM;
  2922. $tool = TOOL_FORUM; //
  2923. // to do: Remove this. For testing purposes only.
  2924. //Session::erase('last_forum_access');
  2925. //Session::erase('whatsnew_post_info');
  2926. $course_id = api_get_course_int_id();
  2927. if (!$_SESSION['last_forum_access']) {
  2928. $sql = "SELECT * FROM ".$tracking_last_tool_access."
  2929. WHERE access_user_id='".Database::escape_string($_user['user_id'])."' AND c_id='".$course_id."' AND access_tool='".Database::escape_string($tool)."'";
  2930. $result = Database::query($sql);
  2931. $row = Database::fetch_array($result);
  2932. $_SESSION['last_forum_access'] = $row['access_date'];
  2933. }
  2934. if (!$_SESSION['whatsnew_post_info']) {
  2935. if ($_SESSION['last_forum_access'] != '') {
  2936. $whatsnew_post_info = array();
  2937. $sql = "SELECT * FROM ".$table_posts." WHERE c_id = $course_id AND post_date>'".Database::escape_string(
  2938. $_SESSION['last_forum_access']
  2939. )."'"; // note: check the performance of this query.
  2940. $result = Database::query($sql);
  2941. while ($row = Database::fetch_array($result)) {
  2942. $whatsnew_post_info[$row['forum_id']][$row['thread_id']][$row['post_id']] = $row['post_date'];
  2943. }
  2944. $_SESSION['whatsnew_post_info'] = $whatsnew_post_info;
  2945. }
  2946. }
  2947. }
  2948. /**
  2949. * With this function we find the number of posts and topics in a given forum.
  2950. *
  2951. * @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
  2952. * 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)
  2953. * @todo consider merging both in one query.
  2954. *
  2955. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2956. * @version february 2006, dokeos 1.8
  2957. *
  2958. * @deprecated the counting mechanism is now inside the function get_forums
  2959. */
  2960. function get_post_topics_of_forum($forum_id)
  2961. {
  2962. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  2963. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  2964. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  2965. $course_id = api_get_course_int_id();
  2966. $sql = "SELECT count(*) as number_of_posts FROM $table_posts WHERE forum_id='".$forum_id."'";
  2967. if (api_is_allowed_to_edit(null, true)) {
  2968. $sql = "SELECT count(*) as number_of_posts
  2969. FROM $table_posts posts, $table_threads threads, $table_item_property item_property
  2970. WHERE
  2971. posts.c_id = $course_id AND
  2972. item_property.c_id = $course_id AND
  2973. posts.forum_id='".Database::escape_string($forum_id)."'
  2974. AND posts.thread_id=threads.thread_id
  2975. AND item_property.ref=threads.thread_id
  2976. AND item_property.visibility<>2
  2977. AND item_property.tool='".TOOL_FORUM_THREAD."'
  2978. ";
  2979. } else {
  2980. $sql = "SELECT count(*) as number_of_posts
  2981. FROM $table_posts posts, $table_threads threads, $table_item_property item_property
  2982. WHERE
  2983. posts.c_id = $course_id AND
  2984. item_property.c_id = $course_id AND
  2985. posts.forum_id='".Database::escape_string($forum_id)."'
  2986. AND posts.thread_id=threads.thread_id
  2987. AND item_property.ref=threads.thread_id
  2988. AND item_property.visibility=1
  2989. AND posts.visible=1
  2990. AND item_property.tool='".TOOL_FORUM_THREAD."'
  2991. ";
  2992. }
  2993. $result = Database::query($sql);
  2994. $row = Database::fetch_array($result);
  2995. $number_of_posts = $row['number_of_posts'];
  2996. // 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.
  2997. if (api_is_allowed_to_edit(null, true)) {
  2998. $sql = "SELECT count(*) as number_of_topics
  2999. FROM $table_threads threads, $table_item_property item_property
  3000. WHERE
  3001. threads.c_id = $course_id AND
  3002. item_property.c_id = $course_id AND
  3003. threads.forum_id='".Database::escape_string($forum_id)."'
  3004. AND item_property.ref=threads.thread_id
  3005. AND item_property.visibility<>2
  3006. AND item_property.tool='".TOOL_FORUM_THREAD."'
  3007. ";
  3008. } else {
  3009. $sql = "SELECT count(*) as number_of_topics
  3010. FROM $table_threads threads, $table_item_property item_property
  3011. WHERE
  3012. threads.c_id = $course_id AND
  3013. item_property.c_id = $course_id AND
  3014. threads.forum_id='".Database::escape_string($forum_id)."'
  3015. AND item_property.ref=threads.thread_id
  3016. AND item_property.visibility=1
  3017. AND item_property.tool='".TOOL_FORUM_THREAD."'
  3018. ";
  3019. }
  3020. $result = Database::query($sql);
  3021. $row = Database::fetch_array($result);
  3022. $number_of_topics = $row['number_of_topics'];
  3023. if ($number_of_topics == '') {
  3024. $number_of_topics = 0; // Due to the nature of the group by this can result in an empty string.
  3025. }
  3026. $return = array('number_of_topics' => $number_of_topics, 'number_of_posts' => $number_of_posts);
  3027. return $return;
  3028. }
  3029. /**
  3030. * This function approves a post = change
  3031. *
  3032. * @param $post_id the id of the post that will be deleted
  3033. * @param $action make the post visible or invisible
  3034. * @return string language variable
  3035. *
  3036. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3037. * @version february 2006, dokeos 1.8
  3038. */
  3039. function approve_post($post_id, $action)
  3040. {
  3041. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  3042. $course_id = api_get_course_int_id();
  3043. if ($action == 'invisible') {
  3044. $visibility_value = 0;
  3045. }
  3046. if ($action == 'visible') {
  3047. $visibility_value = 1;
  3048. handle_mail_cue('post', $post_id);
  3049. }
  3050. $sql = "UPDATE $table_posts SET visible='".Database::escape_string($visibility_value)."'
  3051. WHERE c_id = $course_id AND post_id='".Database::escape_string($post_id)."'";
  3052. $return = Database::query($sql);
  3053. if ($return) {
  3054. return 'PostVisibilityChanged';
  3055. }
  3056. }
  3057. /**
  3058. * This function retrieves all the unapproved messages for a given forum
  3059. * This is needed to display the icon that there are unapproved messages in that thread (only the courseadmin can see this)
  3060. *
  3061. * @param $forum_id the forum where we want to know the unapproved messages of
  3062. * @return array returns
  3063. *
  3064. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3065. * @version february 2006, dokeos 1.8
  3066. */
  3067. function get_unaproved_messages($forum_id)
  3068. {
  3069. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  3070. $course_id = api_get_course_int_id();
  3071. $return_array = array();
  3072. $sql = "SELECT DISTINCT thread_id FROM $table_posts WHERE c_id = $course_id AND forum_id='".Database::escape_string(
  3073. $forum_id
  3074. )."' AND visible='0'";
  3075. $result = Database::query($sql);
  3076. while ($row = Database::fetch_array($result)) {
  3077. $return_array[] = $row['thread_id'];
  3078. }
  3079. return $return_array;
  3080. }
  3081. /**
  3082. * This function sends the notification mails to everybody who stated that they wanted to be informed when a new post
  3083. * was added to a given thread.
  3084. *
  3085. * @param array reply information
  3086. * @return void
  3087. *
  3088. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3089. * @version february 2006, dokeos 1.8
  3090. */
  3091. function send_notification_mails($thread_id, $reply_info)
  3092. {
  3093. $table_mailcue = Database :: get_course_table(TABLE_FORUM_MAIL_QUEUE);
  3094. // First we need to check if
  3095. // 1. the forum category is visible
  3096. // 2. the forum is visible
  3097. // 3. the thread is visible
  3098. // 4. the reply is visible (=when there is)
  3099. $current_thread = get_thread_information($thread_id);
  3100. $current_forum = get_forum_information($current_thread['forum_id']);
  3101. $current_forum_category = get_forumcategory_information($current_forum['forum_category']);
  3102. if ($current_thread['visibility'] == '1' && $current_forum['visibility'] == '1' && ($current_forum_category && $current_forum_category['visibility'] == '1') && $current_forum['approval_direct_post'] != '1') {
  3103. $send_mails = true;
  3104. } else {
  3105. $send_mails = false;
  3106. }
  3107. // The forum category, the forum, the thread and the reply are visible to the user
  3108. if ($send_mails) {
  3109. send_notifications($current_thread['forum_id'], $thread_id);
  3110. } else {
  3111. $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
  3112. $sql = "SELECT * FROM $table_notification WHERE c_id = ".api_get_course_int_id(
  3113. )." AND (forum_id = '".Database::escape_string(
  3114. $current_forum['forum_id']
  3115. )."' OR thread_id = '".Database::escape_string($thread_id)."' ) ";
  3116. $result = Database::query($sql);
  3117. $user_id = api_get_user_id();
  3118. while ($row = Database::fetch_array($result)) {
  3119. $sql_mailcue = "INSERT INTO $table_mailcue (c_id, thread_id, post_id, user_id)
  3120. VALUES (".api_get_course_int_id().", '".Database::escape_string(
  3121. $thread_id
  3122. )."', '".Database::escape_string($reply_info['new_post_id'])."', '$user_id' )";
  3123. Database::query($sql_mailcue);
  3124. }
  3125. }
  3126. }
  3127. /**
  3128. * This function is called whenever something is made visible because there might
  3129. * be new posts and the user might have indicated that (s)he wanted to be
  3130. * informed about the new posts by mail.
  3131. *
  3132. * @param string Content type (post, thread, forum, forum_category)
  3133. * @param int Item DB ID
  3134. * @return string language variable
  3135. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3136. * @version february 2006, dokeos 1.8
  3137. */
  3138. function handle_mail_cue($content, $id)
  3139. {
  3140. $table_mailcue = Database :: get_course_table(TABLE_FORUM_MAIL_QUEUE);
  3141. $table_forums = Database :: get_course_table(TABLE_FORUM);
  3142. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  3143. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  3144. $table_users = Database :: get_main_table(TABLE_MAIN_USER);
  3145. $course_id = api_get_course_int_id();
  3146. // 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.
  3147. if ($content == 'post') {
  3148. // Getting the information about the post (need the thread_id).
  3149. $post_info = get_post_information($id);
  3150. $thread_id = Database::escape_string($post_info['thread_id']);
  3151. // Sending the mail to all the users that wanted to be informed for replies on this thread.
  3152. $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email
  3153. FROM $table_mailcue mailcue, $table_posts posts, $table_users users
  3154. WHERE
  3155. posts.c_id = $course_id AND
  3156. mailcue.c_id = $course_id AND
  3157. posts.thread_id='$thread_id'
  3158. AND posts.post_notification='1'
  3159. AND mailcue.thread_id='$thread_id'
  3160. AND users.user_id=posts.poster_id
  3161. AND users.active=1
  3162. GROUP BY users.email";
  3163. $result = Database::query($sql);
  3164. while ($row = Database::fetch_array($result)) {
  3165. send_mail($row, get_thread_information($post_info['thread_id']));
  3166. }
  3167. // Deleting the relevant entries from the mailcue.
  3168. $sql_delete_mailcue = "DELETE FROM $table_mailcue WHERE c_id = $course_id AND post_id='".Database::escape_string(
  3169. $id
  3170. )."' AND thread_id='".Database::escape_string($post_info['thread_id'])."'";
  3171. //$result = Database::query($sql_delete_mailcue);
  3172. } elseif ($content == 'thread') {
  3173. // Sending the mail to all the users that wanted to be informed for replies on this thread.
  3174. $sql = "SELECT users.firstname, users.lastname, users.user_id, users.email
  3175. FROM $table_mailcue mailcue, $table_posts posts, $table_users users
  3176. WHERE
  3177. posts.c_id = $course_id AND
  3178. mailcue.c_id = $course_id AND
  3179. posts.thread_id='".Database::escape_string($id)."'
  3180. AND posts.post_notification='1'
  3181. AND mailcue.thread_id='".Database::escape_string($id)."'
  3182. AND users.user_id=posts.poster_id
  3183. AND users.active=1
  3184. GROUP BY users.email";
  3185. $result = Database::query($sql);
  3186. while ($row = Database::fetch_array($result)) {
  3187. send_mail($row, get_thread_information($id));
  3188. }
  3189. // Deleting the relevant entries from the mailcue.
  3190. $sql_delete_mailcue = "DELETE FROM $table_mailcue WHERE c_id = $course_id AND thread_id='".Database::escape_string(
  3191. $id
  3192. )."'";
  3193. $result = Database::query($sql_delete_mailcue);
  3194. } elseif ($content == 'forum') {
  3195. $sql = "SELECT thread_id FROM $table_threads WHERE c_id = $course_id AND forum_id='".Database::escape_string(
  3196. $id
  3197. )."'";
  3198. $result = Database::query($sql);
  3199. while ($row = Database::fetch_array($result)) {
  3200. handle_mail_cue('thread', $row['thread_id']);
  3201. }
  3202. } elseif ($content == 'forum_category') {
  3203. $sql = "SELECT forum_id FROM $table_forums WHERE c_id = $course_id AND forum_category ='".Database::escape_string(
  3204. $id
  3205. )."'";
  3206. $result = Database::query($sql);
  3207. while ($row = Database::fetch_array($result)) {
  3208. handle_mail_cue('forum', $row['forum_id']);
  3209. }
  3210. } else {
  3211. return get_lang('Error');
  3212. }
  3213. }
  3214. /**
  3215. * This function sends the mails for the mail notification
  3216. *
  3217. * @param array
  3218. * @param array
  3219. * @return void
  3220. *
  3221. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3222. * @version february 2006, dokeos 1.8
  3223. */
  3224. function send_mail($user_info = array(), $thread_information = array())
  3225. {
  3226. $_course = api_get_course_info();
  3227. $user_id = api_get_user_id();
  3228. $subject = get_lang('NewForumPost').' - '.$_course['official_code'];
  3229. if (isset($thread_information) && is_array($thread_information)) {
  3230. $thread_link = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq(
  3231. ).'&amp;forum='.$thread_information['forum_id'].'&amp;thread='.$thread_information['thread_id'];
  3232. }
  3233. $email_body = get_lang('Dear').' '.api_get_person_name(
  3234. $user_info['firstname'],
  3235. $user_info['lastname'],
  3236. null,
  3237. PERSON_NAME_EMAIL_ADDRESS
  3238. ).", <br />\n\r";
  3239. $email_body .= get_lang('NewForumPost')."\n";
  3240. $email_body .= get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."] - <br />\n";
  3241. $email_body .= get_lang('YouWantedToStayInformed')."<br />\n";
  3242. $email_body .= get_lang('ThreadCanBeFoundHere')." : <br /><a href=\"".$thread_link."\">".$thread_link."</a>\n";
  3243. if ($user_info['user_id'] <> $user_id) {
  3244. MessageManager::send_message(
  3245. $user_info['user_id'],
  3246. $subject,
  3247. $email_body,
  3248. null,
  3249. null,
  3250. null,
  3251. null,
  3252. null,
  3253. null,
  3254. $user_id
  3255. );
  3256. }
  3257. }
  3258. /**
  3259. * This function displays the form for moving a thread to a different (already existing) forum
  3260. * @return void HTML
  3261. *
  3262. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3263. * @version february 2006, dokeos 1.8
  3264. */
  3265. function move_thread_form()
  3266. {
  3267. global $origin;
  3268. $gradebook = Security::remove_XSS($_GET['gradebook']);
  3269. // Initialize the object.
  3270. $form = new FormValidator('movepost', 'post', api_get_self().'?forum='.Security::remove_XSS(
  3271. $_GET['forum']
  3272. ).'&gradebook='.$gradebook.'&thread='.Security::remove_XSS($_GET['thread']).'&action='.Security::remove_XSS(
  3273. $_GET['action']
  3274. ).'&origin='.$origin);
  3275. // The header for the form
  3276. $form->addElement('header', '', get_lang('MoveThread'));
  3277. // Invisible form: the thread_id
  3278. $form->addElement('hidden', 'thread_id', intval($_GET['thread'])); // Note: This has to be cleaned first.
  3279. // the fora
  3280. $forum_categories = get_forum_categories();
  3281. $forums = get_forums();
  3282. $htmlcontent .= '<div class="row">
  3283. <div class="label">
  3284. <span class="form_required">*</span>'.get_lang('MoveTo').'
  3285. </div>
  3286. <div class="formw">';
  3287. $htmlcontent .= '<select name="forum">';
  3288. foreach ($forum_categories as $key => $category) {
  3289. $htmlcontent .= '<optgroup label="'.$category['cat_title'].'">';
  3290. foreach ($forums as $key => $forum) {
  3291. if ($forum['forum_category'] == $category['cat_id']) {
  3292. $htmlcontent .= '<option value="'.$forum['forum_id'].'">'.$forum['forum_title'].'</option>';
  3293. }
  3294. }
  3295. $htmlcontent .= '</optgroup>';
  3296. }
  3297. $htmlcontent .= "</select>";
  3298. $htmlcontent .= ' </div>
  3299. </div>';
  3300. $form->addElement('html', $htmlcontent);
  3301. // The OK button
  3302. $form->addElement('style_submit_button', 'SubmitForum', get_lang('MoveThread'), 'class="save"');
  3303. // Validation or display
  3304. if ($form->validate()) {
  3305. $values = $form->exportValues();
  3306. if (isset($_POST['forum'])) {
  3307. store_move_thread($values);
  3308. }
  3309. } else {
  3310. $form->display();
  3311. }
  3312. }
  3313. /**
  3314. * This function displays the form for moving a post message to a different (already existing) or a new thread.
  3315. * @return void HTML
  3316. *
  3317. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3318. * @version february 2006, dokeos 1.8
  3319. */
  3320. function move_post_form()
  3321. {
  3322. global $origin;
  3323. $gradebook = Security::remove_XSS($_GET['gradebook']);
  3324. // initiate the object
  3325. $form = new FormValidator('movepost', 'post', api_get_self().'?forum='.Security::remove_XSS(
  3326. $_GET['forum']
  3327. ).'&thread='.Security::remove_XSS(
  3328. $_GET['thread']
  3329. ).'&origin='.$origin.'&gradebook='.$gradebook.'&post='.Security::remove_XSS(
  3330. $_GET['post']
  3331. ).'&action='.Security::remove_XSS($_GET['action']).'&post='.Security::remove_XSS($_GET['post']));
  3332. // The header for the form
  3333. $form->addElement('header', '', get_lang('MovePost'));
  3334. // Invisible form: the post_id
  3335. $form->addElement('hidden', 'post_id', strval(intval($_GET['post']))); // Note: This has to be cleaned first.
  3336. // Dropdown list: Threads of this forum
  3337. $threads = get_threads(strval(intval($_GET['forum']))); // Note: This has to be cleaned.
  3338. //my_print_r($threads);
  3339. $threads_list[0] = get_lang('ANewThread');
  3340. foreach ($threads as $key => $value) {
  3341. $threads_list[$value['thread_id']] = $value['thread_title'];
  3342. }
  3343. $form->addElement('select', 'thread', get_lang('MoveToThread'), $threads_list);
  3344. $form->applyFilter('thread', 'html_filter');
  3345. // The OK button
  3346. $form->addElement('style_submit_button', 'submit', get_lang('MovePost'), 'class="save"');
  3347. // Setting the rules
  3348. $form->addRule('thread', get_lang('ThisFieldIsRequired'), 'required');
  3349. // Validation or display
  3350. if ($form->validate()) {
  3351. $values = $form->exportValues();
  3352. store_move_post($values);
  3353. } else {
  3354. $form->display();
  3355. }
  3356. }
  3357. /**
  3358. *
  3359. * @param array
  3360. * @return string HTML language variable
  3361. *
  3362. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3363. * @version february 2006, dokeos 1.8
  3364. */
  3365. function store_move_post($values)
  3366. {
  3367. $_course = api_get_course_info();
  3368. $table_forums = Database :: get_course_table(TABLE_FORUM);
  3369. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  3370. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  3371. $course_id = api_get_course_int_id();
  3372. if ($values['thread'] == '0') {
  3373. $current_post = get_post_information($values['post_id']);
  3374. // Storing a new thread.
  3375. $sql = "INSERT INTO $table_threads (c_id, thread_title, forum_id, thread_poster_id, thread_poster_name, thread_last_post, thread_date)
  3376. VALUES (
  3377. ".$course_id.",
  3378. '".Database::escape_string($current_post['post_title'])."',
  3379. '".Database::escape_string($current_post['forum_id'])."',
  3380. '".Database::escape_string($current_post['poster_id'])."',
  3381. '".Database::escape_string($current_post['poster_name'])."',
  3382. '".Database::escape_string($values['post_id'])."',
  3383. '".Database::escape_string($current_post['post_date'])."'
  3384. )";
  3385. $result = Database::query($sql);
  3386. $new_thread_id = Database::insert_id();
  3387. api_item_property_update($_course, TOOL_FORUM_THREAD, $new_thread_id, 'visible', $current_post['poster_id']);
  3388. // Moving the post to the newly created thread.
  3389. $sql = "UPDATE $table_posts SET thread_id='".Database::escape_string(
  3390. $new_thread_id
  3391. )."', post_parent_id='0' WHERE c_id = $course_id AND post_id='".Database::escape_string($values['post_id'])."'";
  3392. $result = Database::query($sql);
  3393. // Resetting the parent_id of the thread to 0 for all those who had this moved post as parent.
  3394. $sql = "UPDATE $table_posts SET post_parent_id='0' WHERE c_id = $course_id AND post_parent_id='".Database::escape_string(
  3395. $values['post_id']
  3396. )."'";
  3397. $result = Database::query($sql);
  3398. // Updating updating the number of threads in the forum.
  3399. $sql = "UPDATE $table_forums SET forum_threads=forum_threads+1 WHERE c_id = $course_id AND forum_id='".Database::escape_string(
  3400. $current_post['forum_id']
  3401. )."'";
  3402. $result = Database::query($sql);
  3403. // Resetting the last post of the old thread and decreasing the number of replies and the thread.
  3404. $sql = "SELECT * FROM $table_posts WHERE c_id = $course_id AND thread_id='".Database::escape_string(
  3405. $current_post['thread_id']
  3406. )."' ORDER BY post_id DESC";
  3407. $result = Database::query($sql);
  3408. $row = Database::fetch_array($result);
  3409. $sql = "UPDATE $table_threads SET thread_last_post='".$row['post_id']."', thread_replies=thread_replies-1 WHERE c_id = $course_id AND thread_id='".Database::escape_string(
  3410. $current_post['thread_id']
  3411. )."'";
  3412. $result = Database::query($sql);
  3413. } else {
  3414. // Moving to the chosen thread.
  3415. //Old code
  3416. //$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'])."'";
  3417. //$result = Database::query($sql);
  3418. // Resetting the parent_id of the thread to 0 for all those who had this moved post as parent.
  3419. //$sql = "UPDATE $table_posts SET post_parent_id='0' WHERE post_parent_id='".Database::escape_string($values['post_id'])."'";
  3420. //$result = Database::query($sql);
  3421. // If this post is the last post of the thread we must update the thread_last_post with a new post_id
  3422. // Search for the original thread_id
  3423. $sql = "SELECT thread_id FROM ".$table_posts." WHERE c_id = $course_id AND post_id = '".$values['post_id']."' ";
  3424. $result = Database::query($sql);
  3425. $row = Database::fetch_array($result);
  3426. $original_thread_id = $row['thread_id'];
  3427. $sql = "SELECT thread_last_post FROM ".$table_threads." WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
  3428. $result = Database::query($sql);
  3429. $row = Database::fetch_array($result);
  3430. $thread_is_last_post = $row['thread_last_post'];
  3431. // If is this thread, update the thread_last_post with the last one.
  3432. if ($thread_is_last_post == $values['post_id']) {
  3433. $sql = "SELECT post_id FROM ".$table_posts." WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' AND post_id <> '".$values['post_id']."' ORDER BY post_date DESC LIMIT 1";
  3434. $result = Database::query($sql);
  3435. $row = Database::fetch_array($result);
  3436. $thread_new_last_post = $row['post_id'];
  3437. $sql = "UPDATE ".$table_threads." SET thread_last_post = '".$thread_new_last_post."' WHERE c_id = $course_id AND thread_id = '".$original_thread_id."' ";
  3438. $result = Database::query($sql);
  3439. }
  3440. $sql = "UPDATE $table_threads SET thread_replies=thread_replies-1 WHERE c_id = $course_id AND thread_id='".$original_thread_id."'";
  3441. $result = Database::query($sql);
  3442. // moving to the chosen thread
  3443. $sql = "UPDATE $table_posts SET thread_id='".intval(
  3444. $_POST['thread']
  3445. )."', post_parent_id='0' WHERE c_id = $course_id AND post_id='".intval($values['post_id'])."'";
  3446. $result = Database::query($sql);
  3447. // resetting the parent_id of the thread to 0 for all those who had this moved post as parent
  3448. $sql = "UPDATE $table_posts SET post_parent_id='0' WHERE c_id = $course_id AND post_parent_id='".intval(
  3449. $values['post_id']
  3450. )."'";
  3451. $result = Database::query($sql);
  3452. $sql = "UPDATE $table_threads SET thread_replies=thread_replies+1 WHERE c_id = $course_id AND thread_id='".intval(
  3453. $_POST['thread']
  3454. )."'";
  3455. $result = Database::query($sql);
  3456. }
  3457. return get_lang('ThreadMoved');
  3458. }
  3459. /**
  3460. *
  3461. * @param array
  3462. * @return string HTML language variable
  3463. *
  3464. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3465. * @version february 2006, dokeos 1.8
  3466. */
  3467. function store_move_thread($values)
  3468. {
  3469. $_course = api_get_course_info();
  3470. $table_forums = Database :: get_course_table(TABLE_FORUM);
  3471. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  3472. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  3473. $course_id = api_get_course_int_id();
  3474. // Change the thread table: Setting the forum_id to the new forum.
  3475. $sql = "UPDATE $table_threads SET forum_id='".Database::escape_string(
  3476. $_POST['forum']
  3477. )."' WHERE c_id = $course_id AND thread_id='".Database::escape_string($_POST['thread_id'])."'";
  3478. $result = Database::query($sql);
  3479. // Changing all the posts of the thread: setting the forum_id to the new forum.
  3480. $sql = "UPDATE $table_posts SET forum_id='".Database::escape_string(
  3481. $_POST['forum']
  3482. )."' WHERE c_id = $course_id AND thread_id='".Database::escape_string($_POST['thread_id'])."'";
  3483. $result = Database::query($sql);
  3484. return get_lang('ThreadMoved');
  3485. }
  3486. /**
  3487. * Prepares a string for displaying by highlighting the search results inside, if any.
  3488. * @param string $input The input string.
  3489. * @return string The same string with highlighted hits inside.
  3490. *
  3491. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, February 2006 - the initial version.
  3492. * @author Ivan Tcholakov, March 2011 - adaptation for Chamilo LMS.
  3493. */
  3494. function prepare4display($input)
  3495. {
  3496. static $highlightcolors = array('yellow', '#33CC33', '#3399CC', '#9999FF', '#33CC33');
  3497. static $search;
  3498. if (!isset($search)) {
  3499. if (isset($_POST['search_term'])) {
  3500. $search = $_POST['search_term']; // No html at all.
  3501. } elseif (isset($_GET['search'])) {
  3502. $search = $_GET['search'];
  3503. } else {
  3504. $search = '';
  3505. }
  3506. }
  3507. if (!empty($search)) {
  3508. if (strstr($search, '+')) {
  3509. $search_terms = explode('+', $search);
  3510. } else {
  3511. $search_terms[] = trim($search);
  3512. }
  3513. $counter = 0;
  3514. foreach ($search_terms as $key => $search_term) {
  3515. $input = api_preg_replace(
  3516. '/'.preg_quote(trim($search_term), '/').'/i',
  3517. '<span style="background-color: '.$highlightcolors[$counter].'">$0</span>',
  3518. $input
  3519. );
  3520. $counter++;
  3521. }
  3522. }
  3523. // TODO: Security should be implemented outside this function.
  3524. // Change this to COURSEMANAGERLOWSECURITY or COURSEMANAGER to lower filtering and allow more styles (see comments of Security::remove_XSS() method to learn about other levels).
  3525. return Security::remove_XSS($input, STUDENT, true);
  3526. }
  3527. /**
  3528. * Display the search form for the forum and display the search results
  3529. * @return void display an HTML search results
  3530. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  3531. * @version march 2008, dokeos 1.8.5
  3532. */
  3533. function forum_search()
  3534. {
  3535. global $origin;
  3536. // Initialize the object.
  3537. $form = new FormValidator('forumsearch', 'post', 'forumsearch.php?origin='.$origin.'');
  3538. // Settting the form elements.
  3539. $form->addElement('header', '', get_lang('ForumSearch'));
  3540. $form->addElement('text', 'search_term', get_lang('SearchTerm'), 'class="input_titles" id="search_title"');
  3541. $form->applyFilter('search_term', 'html_filter');
  3542. $form->addElement(
  3543. 'static',
  3544. 'search_information',
  3545. '',
  3546. get_lang('ForumSearchInformation') /*, $dissertation[$_GET['opleidingsonderdeelcode']]['code']*/
  3547. );
  3548. $form->addElement('style_submit_button', null, get_lang('Search'), 'class="search"');
  3549. // Setting the rules.
  3550. $form->addRule('search_term', get_lang('ThisFieldIsRequired'), 'required');
  3551. $form->addRule('search_term', get_lang('TooShort'), 'minlength', 3);
  3552. // Validation or display.
  3553. if ($form->validate()) {
  3554. $values = $form->exportValues();
  3555. $form->setDefaults($values);
  3556. $form->display();
  3557. // Display the search results.
  3558. display_forum_search_results(stripslashes($values['search_term']));
  3559. } else {
  3560. $form->display();
  3561. }
  3562. }
  3563. /**
  3564. * Display the search results
  3565. * @param string
  3566. * @return void display the results
  3567. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  3568. * @version march 2008, dokeos 1.8.5
  3569. */
  3570. function display_forum_search_results($search_term)
  3571. {
  3572. global $origin;
  3573. $table_categories = Database :: get_course_table(TABLE_FORUM_CATEGORY);
  3574. $table_forums = Database :: get_course_table(TABLE_FORUM);
  3575. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  3576. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  3577. $gradebook = Security::remove_XSS($_GET['gradebook']);
  3578. $course_id = api_get_course_int_id();
  3579. // Defining the search strings as an array.
  3580. if (strstr($search_term, '+')) {
  3581. $search_terms = explode('+', $search_term);
  3582. } else {
  3583. $search_terms[] = $search_term;
  3584. }
  3585. // Search restriction.
  3586. foreach ($search_terms as $key => $value) {
  3587. $search_restriction[] = "(posts.post_title LIKE '%".Database::escape_string(trim($value))."%'
  3588. OR posts.post_text LIKE '%".Database::escape_string(trim($value))."%')";
  3589. }
  3590. $sql = "SELECT * FROM $table_posts posts
  3591. WHERE c_id = $course_id AND ".implode(' AND ', $search_restriction)."
  3592. GROUP BY posts.post_id";
  3593. // Getting all the information of the forum categories.
  3594. $forum_categories_list = get_forum_categories();
  3595. // Getting all the information of the forums.
  3596. $forum_list = get_forums();
  3597. $result = Database::query($sql);
  3598. while ($row = Database::fetch_array($result, 'ASSOC')) {
  3599. $display_result = false;
  3600. /*
  3601. We only show it when
  3602. 1. forum cateogory is visible
  3603. 2. forum is visible
  3604. 3. thread is visible (to do)
  3605. 4. post is visible
  3606. */
  3607. if (!api_is_allowed_to_edit(null, true)) {
  3608. if ($forum_categories_list[$row['forum_id']['forum_category']]['visibility'] == '1' AND $forum_list[$row['forum_id']]['visibility'] == '1' AND $row['visible'] == '1') {
  3609. $display_result = true;
  3610. }
  3611. } else {
  3612. $display_result = true;
  3613. }
  3614. if ($display_result) {
  3615. $search_results_item = '<li><a href="viewforumcategory.php?forumcategory='.$forum_list[$row['forum_id']]['forum_category'].'&amp;origin='.$origin.'&amp;search='.urlencode(
  3616. $search_term
  3617. ).'">'.prepare4display(
  3618. $forum_categories_list[$row['forum_id']['forum_category']]['cat_title']
  3619. ).'</a> &gt; ';
  3620. $search_results_item .= '<a href="viewforum.php?forum='.$row['forum_id'].'&amp;origin='.$origin.'&amp;search='.urlencode(
  3621. $search_term
  3622. ).'">'.prepare4display($forum_list[$row['forum_id']]['forum_title']).'</a> &gt; ';
  3623. //$search_results_item .= '<a href="">THREAD</a> &gt; ';
  3624. $search_results_item .= '<a href="viewthread.php?forum='.$row['forum_id'].'&amp;gradebook='.$gradebook.'&amp;origin='.$origin.'&amp;thread='.$row['thread_id'].'&amp;search='.urlencode(
  3625. $search_term
  3626. ).'">'.prepare4display($row['post_title']).'</a>';
  3627. $search_results_item .= '<br />';
  3628. if (api_strlen($row['post_title']) > 200) {
  3629. $search_results_item .= prepare4display(api_substr(strip_tags($row['post_title']), 0, 200)).'...';
  3630. } else {
  3631. $search_results_item .= prepare4display($row['post_title']);
  3632. }
  3633. $search_results_item .= '</li>';
  3634. $search_results[] = $search_results_item;
  3635. }
  3636. }
  3637. echo '<legend>'.count($search_results).' '.get_lang('ForumSearchResults').'</legend>';
  3638. echo '<ol>';
  3639. if ($search_results) {
  3640. echo implode($search_results);
  3641. }
  3642. echo '</ol>';
  3643. }
  3644. /**
  3645. * Return the link to the forum search page
  3646. *
  3647. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  3648. * @version April 2008, dokeos 1.8.5
  3649. */
  3650. function search_link()
  3651. {
  3652. global $origin;
  3653. $return = '';
  3654. if ($origin != 'learnpath') {
  3655. $return = '<a href="forumsearch.php?'.api_get_cidreq().'&amp;gidReq='.api_get_group_id(
  3656. ).'&amp;action=search&amp;origin='.$origin.'"> ';
  3657. $return .= Display::return_icon('search.png', get_lang('Search'), '', ICON_SIZE_MEDIUM).'</a>';
  3658. if (!empty($_GET['search'])) {
  3659. $return .= ': '.Security::remove_XSS($_GET['search']).' ';
  3660. $url = api_get_self().'?';
  3661. $url_parameter = array();
  3662. foreach ($_GET as $key => $value) {
  3663. if ($key != 'search') {
  3664. $url_parameter[] = Security::remove_XSS($key).'='.Security::remove_XSS($value);
  3665. }
  3666. }
  3667. $url = $url.implode('&amp;', $url_parameter);
  3668. $return .= '<a href="'.$url.'">'.Display::return_icon('delete.gif', get_lang('RemoveSearchResults')).'</a>';
  3669. }
  3670. }
  3671. return $return;
  3672. }
  3673. /**
  3674. * This function adds an attachment file into a forum
  3675. * @param string a comment about file
  3676. * @param int last id from forum_post table
  3677. * @return void
  3678. */
  3679. function add_forum_attachment_file($file_comment, $last_id)
  3680. {
  3681. $_course = api_get_course_info();
  3682. $agenda_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
  3683. // Storing the attachments
  3684. if (!empty($_FILES['user_upload']['name'])) {
  3685. $upload_ok = FileManager::process_uploaded_file($_FILES['user_upload']);
  3686. }
  3687. if (!empty($upload_ok)) {
  3688. $course_dir = $_course['path'].'/upload/forum';
  3689. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  3690. $updir = $sys_course_path.$course_dir;
  3691. // Try to add an extension to the file if it hasn't one.
  3692. $new_file_name = FileManager::add_ext_on_mime(
  3693. stripslashes($_FILES['user_upload']['name']),
  3694. $_FILES['user_upload']['type']
  3695. );
  3696. // User's file name
  3697. $file_name = $_FILES['user_upload']['name'];
  3698. if (!FileManager::filter_extension($new_file_name)) {
  3699. Display :: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
  3700. } else {
  3701. $new_file_name = uniqid('');
  3702. $new_path = $updir.'/'.$new_file_name;
  3703. $result = @move_uploaded_file($_FILES['user_upload']['tmp_name'], $new_path);
  3704. $safe_file_comment = Database::escape_string($file_comment);
  3705. $safe_file_name = Database::escape_string($file_name);
  3706. $safe_new_file_name = Database::escape_string($new_file_name);
  3707. $last_id = intval($last_id);
  3708. // Storing the attachments if any.
  3709. if ($result) {
  3710. $sql = "INSERT INTO $agenda_forum_attachment (c_id, filename, comment, path, post_id, size)
  3711. VALUES (".api_get_course_int_id(
  3712. ).", '$safe_file_name', '$safe_file_comment', '$safe_new_file_name' , '$last_id', '".intval(
  3713. $_FILES['user_upload']['size']
  3714. )."' )";
  3715. $result = Database::query($sql);
  3716. $message .= ' / '.get_lang('FileUploadSucces').'<br />';
  3717. $last_id_file = Database::insert_id();
  3718. api_item_property_update(
  3719. $_course,
  3720. TOOL_FORUM_ATTACH,
  3721. $last_id_file,
  3722. 'ForumAttachmentAdded',
  3723. api_get_user_id()
  3724. );
  3725. }
  3726. }
  3727. }
  3728. }
  3729. /**
  3730. * This function edits an attachment file into a forum
  3731. * @param string a comment about file
  3732. * @param int Post Id
  3733. * @param int attachment file Id
  3734. * @return void
  3735. */
  3736. function edit_forum_attachment_file($file_comment, $post_id, $id_attach)
  3737. {
  3738. $_course = api_get_course_info();
  3739. $table_forum_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
  3740. $course_id = api_get_course_int_id();
  3741. // Storing the attachments.
  3742. if (!empty($_FILES['user_upload']['name'])) {
  3743. $upload_ok = FileManager::process_uploaded_file($_FILES['user_upload']);
  3744. }
  3745. if (!empty($upload_ok)) {
  3746. $course_dir = $_course['path'].'/upload/forum';
  3747. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  3748. $updir = $sys_course_path.$course_dir;
  3749. // Try to add an extension to the file if it hasn't one.
  3750. $new_file_name = FileManager::add_ext_on_mime(
  3751. stripslashes($_FILES['user_upload']['name']),
  3752. $_FILES['user_upload']['type']
  3753. );
  3754. // User's file name
  3755. $file_name = $_FILES['user_upload']['name'];
  3756. if (!FileManager::filter_extension($new_file_name)) {
  3757. Display :: display_error_message(get_lang('UplUnableToSaveFileFilteredExtension'));
  3758. } else {
  3759. $new_file_name = uniqid('');
  3760. $new_path = $updir.'/'.$new_file_name;
  3761. $result = @move_uploaded_file($_FILES['user_upload']['tmp_name'], $new_path);
  3762. $safe_file_comment = Database::escape_string($file_comment);
  3763. $safe_file_name = Database::escape_string($file_name);
  3764. $safe_new_file_name = Database::escape_string($new_file_name);
  3765. $safe_post_id = (int)$post_id;
  3766. $safe_id_attach = (int)$id_attach;
  3767. // Storing the attachments if any.
  3768. if ($result) {
  3769. $sql = "UPDATE $table_forum_attachment SET filename = '$safe_file_name', comment = '$safe_file_comment', path = '$safe_new_file_name', post_id = '$safe_post_id', size ='".$_FILES['user_upload']['size']."'
  3770. WHERE c_id = $course_id AND id = '$safe_id_attach'";
  3771. $result = Database::query($sql);
  3772. api_item_property_update(
  3773. $_course,
  3774. TOOL_FORUM_ATTACH,
  3775. $safe_id_attach,
  3776. 'ForumAttachmentUpdated',
  3777. api_get_user_id()
  3778. );
  3779. }
  3780. }
  3781. }
  3782. }
  3783. /**
  3784. * Show a list with all the attachments according to the post's id
  3785. * @param the post's id
  3786. * @return array with the post info
  3787. * @author Julio Montoya Dokeos
  3788. * @version avril 2008, dokeos 1.8.5
  3789. */
  3790. function get_attachment($post_id)
  3791. {
  3792. $forum_table_attachment = Database :: get_course_table(TABLE_FORUM_ATTACHMENT);
  3793. $course_id = api_get_course_int_id();
  3794. $row = array();
  3795. $post_id = intval($post_id);
  3796. $sql = "SELECT id, path, filename,comment FROM $forum_table_attachment
  3797. WHERE c_id = $course_id AND post_id = $post_id";
  3798. $result = Database::query($sql);
  3799. if (Database::num_rows($result) != 0) {
  3800. $row = Database::fetch_array($result);
  3801. }
  3802. return $row;
  3803. }
  3804. /**
  3805. * Delete the all the attachments from the DB and the file according to the post's id or attach id(optional)
  3806. * @param post id
  3807. * @param attach id (optional)
  3808. * @return void
  3809. * @author Julio Montoya Dokeos
  3810. * @version avril 2008, dokeos 1.8.5
  3811. */
  3812. function delete_attachment($post_id, $id_attach = 0)
  3813. {
  3814. $_course = api_get_course_info();
  3815. $forum_table_attachment = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
  3816. $course_id = api_get_course_int_id();
  3817. $cond = (!empty($id_attach)) ? " id = ".(int)$id_attach."" : " post_id = ".(int)$post_id."";
  3818. $sql = "SELECT path FROM $forum_table_attachment WHERE c_id = $course_id AND $cond";
  3819. $res = Database::query($sql);
  3820. $row = Database::fetch_array($res);
  3821. $course_dir = $_course['path'].'/upload/forum';
  3822. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  3823. $updir = $sys_course_path.$course_dir;
  3824. $my_path = isset($row['path']) ? $row['path'] : null;
  3825. $file = $updir.'/'.$my_path;
  3826. if (Security::check_abs_path($file, $updir)) {
  3827. @unlink($file);
  3828. }
  3829. // Delete from forum_attachment table.
  3830. $sql = "DELETE FROM $forum_table_attachment WHERE c_id = $course_id AND $cond ";
  3831. $result = Database::query($sql);
  3832. $last_id_file = Database::insert_id();
  3833. // Update item_property.
  3834. api_item_property_update($_course, TOOL_FORUM_ATTACH, $id_attach, 'ForumAttachmentDelete', api_get_user_id());
  3835. if (!empty($result) && !empty($id_attach)) {
  3836. $message = get_lang(get_lang('AttachmentFileDeleteSuccess'));
  3837. Display::display_confirmation_message($message);
  3838. }
  3839. }
  3840. /**
  3841. * This function gets all the forum information of the all the forum of the group
  3842. *
  3843. * @param integer $group_id the id of the group we need the fora of (see forum.forum_of_group)
  3844. * @return array
  3845. *
  3846. * @todo this is basically the same code as the get_forums function. Consider merging the two.
  3847. */
  3848. function get_forums_of_group($group_id)
  3849. {
  3850. $table_forums = Database :: get_course_table(TABLE_FORUM);
  3851. $table_threads = Database :: get_course_table(TABLE_FORUM_THREAD);
  3852. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  3853. $table_item_property = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  3854. $table_users = Database :: get_main_table(TABLE_MAIN_USER);
  3855. $course_id = api_get_course_int_id();
  3856. // Student
  3857. // Select all the forum information of all forums (that are visible to students).
  3858. $sql = "SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  3859. WHERE forum.forum_of_group = '".Database::escape_string($group_id)."' AND
  3860. forum.c_id = $course_id AND
  3861. item_properties.c_id = $course_id AND
  3862. forum.forum_id=item_properties.ref AND
  3863. item_properties.visibility=1 AND
  3864. item_properties.tool='".TOOL_FORUM."'
  3865. ORDER BY forum.forum_order ASC";
  3866. // Select the number of threads of the forums (only the threads that are visible).
  3867. $sql2 = "SELECT count(thread_id) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  3868. WHERE threads.thread_id=item_properties.ref AND
  3869. threads.c_id = $course_id AND
  3870. item_properties.c_id = $course_id AND
  3871. item_properties.visibility=1 AND
  3872. item_properties.tool='".TOOL_FORUM_THREAD."'
  3873. GROUP BY threads.forum_id";
  3874. // Select the number of posts of the forum (post that are visible and that are in a thread that is visible).
  3875. $sql3 = "SELECT count(post_id) AS number_of_posts, posts.forum_id FROM $table_posts posts, $table_threads threads, ".$table_item_property." item_properties
  3876. WHERE posts.visible=1 AND
  3877. posts.c_id = $course_id AND
  3878. item_properties.c_id = $course_id AND
  3879. threads.c_id = $course_id
  3880. AND posts.thread_id=threads.thread_id
  3881. AND threads.thread_id=item_properties.ref
  3882. AND item_properties.visibility=1
  3883. AND item_properties.tool='".TOOL_FORUM_THREAD."'
  3884. GROUP BY threads.forum_id";
  3885. //-------------- Course Admin -----------------//
  3886. if (is_allowed_to_edit()) {
  3887. // Select all the forum information of all forums (that are not deleted).
  3888. $sql = "SELECT * FROM ".$table_forums." forum , ".$table_item_property." item_properties
  3889. WHERE forum.forum_of_group = '".Database::escape_string($group_id)."' AND
  3890. forum.c_id = $course_id AND
  3891. item_properties.c_id = $course_id AND
  3892. forum.forum_id=item_properties.ref AND
  3893. item_properties.visibility<>2 AND
  3894. item_properties.tool='".TOOL_FORUM."'
  3895. ORDER BY forum_order ASC";
  3896. // Select the number of threads of the forums (only the threads that are not deleted).
  3897. $sql2 = "SELECT count(thread_id) AS number_of_threads, threads.forum_id FROM $table_threads threads, ".$table_item_property." item_properties
  3898. WHERE threads.thread_id=item_properties.ref AND
  3899. threads.c_id = $course_id AND
  3900. item_properties.c_id = $course_id AND
  3901. item_properties.visibility<>2 AND
  3902. item_properties.tool='".TOOL_FORUM_THREAD."'
  3903. GROUP BY threads.forum_id";
  3904. // Select the number of posts of the forum.
  3905. $sql3 = "SELECT count(post_id) AS number_of_posts, forum_id FROM $table_posts WHERE c_id = $course_id GROUP BY forum_id";
  3906. }
  3907. // Handling all the forum information.
  3908. $result = Database::query($sql);
  3909. while ($row = Database::fetch_array($result, 'ASSOC')) {
  3910. $forum_list[$row['forum_id']] = $row;
  3911. }
  3912. // Handling the threadcount information.
  3913. $result2 = Database::query($sql2);
  3914. while ($row2 = Database::fetch_array($result2, 'ASSOC')) {
  3915. if (is_array($forum_list)) {
  3916. if (array_key_exists($row2['forum_id'], $forum_list)) {
  3917. $forum_list[$row2['forum_id']]['number_of_threads'] = $row2['number_of_threads'];
  3918. }
  3919. }
  3920. }
  3921. // Handling the postcount information.
  3922. $result3 = Database::query($sql3);
  3923. while ($row3 = Database::fetch_array($result3, 'ASSOC')) {
  3924. if (is_array($forum_list)) {
  3925. if (array_key_exists(
  3926. $row3['forum_id'],
  3927. $forum_list
  3928. )
  3929. ) { // This is needed because sql3 takes also the deleted forums into account.
  3930. $forum_list[$row3['forum_id']]['number_of_posts'] = $row3['number_of_posts'];
  3931. }
  3932. }
  3933. }
  3934. // Finding the last post information (last_post_id, last_poster_id, last_post_date, last_poster_name, last_poster_lastname, last_poster_firstname).
  3935. if (is_array($forum_list)) {
  3936. foreach ($forum_list as $key => $value) {
  3937. $last_post_info_of_forum = get_last_post_information($key, is_allowed_to_edit());
  3938. $forum_list[$key]['last_post_id'] = $last_post_info_of_forum['last_post_id'];
  3939. $forum_list[$key]['last_poster_id'] = $last_post_info_of_forum['last_poster_id'];
  3940. $forum_list[$key]['last_post_date'] = $last_post_info_of_forum['last_post_date'];
  3941. $forum_list[$key]['last_poster_name'] = $last_post_info_of_forum['last_poster_name'];
  3942. $forum_list[$key]['last_poster_lastname'] = $last_post_info_of_forum['last_poster_lastname'];
  3943. $forum_list[$key]['last_poster_firstname'] = $last_post_info_of_forum['last_poster_firstname'];
  3944. }
  3945. }
  3946. return $forum_list;
  3947. }
  3948. /**
  3949. * This function stores which users have to be notified of which forums or threads
  3950. *
  3951. * @param string $content does the user want to be notified about a forum or about a thread
  3952. * @param integer $id the id of the forum or thread
  3953. * @return string language variable
  3954. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  3955. * @version May 2008, dokeos 1.8.5
  3956. * @since May 2008, dokeos 1.8.5
  3957. */
  3958. function set_notification($content, $id, $add_only = false)
  3959. {
  3960. global $_user;
  3961. // Database table definition
  3962. $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
  3963. $course_id = api_get_course_int_id();
  3964. // Which database field do we have to store the id in?
  3965. if ($content == 'forum') {
  3966. $database_field = 'forum_id';
  3967. } else {
  3968. $database_field = 'thread_id';
  3969. }
  3970. // First we check if the notification is already set for this.
  3971. $sql = "SELECT * FROM $table_notification WHERE c_id = $course_id AND $database_field = '".Database::escape_string(
  3972. $id
  3973. )."' AND user_id = '".Database::escape_string($_user['user_id'])."'";
  3974. $result = Database::query($sql);
  3975. $total = Database::num_rows($result);
  3976. // 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).
  3977. if ($total <= 0) {
  3978. $sql = "INSERT INTO $table_notification (c_id, $database_field, user_id) VALUES (".$course_id.", '".Database::escape_string(
  3979. $id
  3980. )."','".Database::escape_string($_user['user_id'])."')";
  3981. $result = Database::query($sql);
  3982. Session::erase('forum_notification');
  3983. get_notifications_of_user(0, true);
  3984. return get_lang('YouWillBeNotifiedOfNewPosts');
  3985. } else {
  3986. if (!$add_only) {
  3987. $sql = "DELETE FROM $table_notification
  3988. WHERE c_id = $course_id AND $database_field = '".Database::escape_string(
  3989. $id
  3990. )."' AND user_id = '".Database::escape_string($_user['user_id'])."'";
  3991. $result = Database::query($sql);
  3992. Session::erase('forum_notification');
  3993. get_notifications_of_user(0, true);
  3994. return get_lang('YouWillNoLongerBeNotifiedOfNewPosts');
  3995. }
  3996. }
  3997. }
  3998. /**
  3999. * This function retrieves all the email adresses of the users who wanted to be notified
  4000. * about a new post in a certain forum or thread
  4001. *
  4002. * @param string $content does the user want to be notified about a forum or about a thread
  4003. * @param integer $id the id of the forum or thread
  4004. * @return array returns
  4005. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  4006. * @version May 2008, dokeos 1.8.5
  4007. * @since May 2008, dokeos 1.8.5
  4008. */
  4009. function get_notifications($content, $id)
  4010. {
  4011. // Database table definition
  4012. $table_users = Database::get_main_table(TABLE_MAIN_USER);
  4013. $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
  4014. $course_id = api_get_course_int_id();
  4015. // Which database field contains the notification?
  4016. if ($content == 'forum') {
  4017. $database_field = 'forum_id';
  4018. } else {
  4019. $database_field = 'thread_id';
  4020. }
  4021. $sql = "SELECT user.user_id, user.firstname, user.lastname, user.email, user.user_id user
  4022. FROM $table_users user, $table_notification notification
  4023. WHERE notification.c_id = $course_id AND user.active = 1 AND
  4024. user.user_id = notification.user_id AND
  4025. notification.$database_field= '".Database::escape_string($id)."'";
  4026. $result = Database::query($sql);
  4027. $return = array();
  4028. while ($row = Database::fetch_array($result)) {
  4029. $return['user'.$row['user_id']] = array('email' => $row['email'], 'user_id' => $row['user_id']);
  4030. }
  4031. return $return;
  4032. }
  4033. /**
  4034. * Get all the users who need to receive a notification of a new post (those subscribed to
  4035. * the forum or the thread)
  4036. *
  4037. * @param integer $forum_id the id of the forum
  4038. * @param integer $thread_id the id of the thread
  4039. * @param integer $post_id the id of the post
  4040. * @return bool
  4041. *
  4042. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  4043. * @version May 2008, dokeos 1.8.5
  4044. * @since May 2008, dokeos 1.8.5
  4045. */
  4046. function send_notifications($forum_id = 0, $thread_id = 0, $post_id = 0)
  4047. {
  4048. global $_user;
  4049. $_course = api_get_course_info();
  4050. // The content of the mail
  4051. $thread_link = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq(
  4052. ).'&amp;forum='.$forum_id.'&amp;thread='.$thread_id;
  4053. // Users who subscribed to the forum
  4054. if ($forum_id != 0) {
  4055. $users_to_be_notified_by_forum = get_notifications('forum', $forum_id);
  4056. } else {
  4057. return false;
  4058. }
  4059. $current_thread = get_thread_information($thread_id);
  4060. $current_forum = get_forum_information($current_thread['forum_id']);
  4061. $subject = get_lang(
  4062. 'NewForumPost'
  4063. ).' - '.$_course['official_code'].' - '.$current_forum['forum_title'].' - '.$current_thread['thread_title'];
  4064. // User who subscribed to the thread
  4065. if ($thread_id != 0) {
  4066. $users_to_be_notified_by_thread = get_notifications('thread', $thread_id);
  4067. }
  4068. // Merging the two
  4069. $users_to_be_notified = array_merge($users_to_be_notified_by_forum, $users_to_be_notified_by_thread);
  4070. $sender_id = api_get_user_id();
  4071. if (is_array($users_to_be_notified)) {
  4072. foreach ($users_to_be_notified as $value) {
  4073. if ($value['email'] != $_user['email']) {
  4074. $user_info = api_get_user_info($value['user_id']);
  4075. $email_body = get_lang('Dear').' '.api_get_person_name(
  4076. $user_info['firstname'],
  4077. $user_info['lastname'],
  4078. null,
  4079. PERSON_NAME_EMAIL_ADDRESS
  4080. ).", <br />\n\r";
  4081. $email_body .= get_lang(
  4082. 'NewForumPost'
  4083. ).": ".$current_forum['forum_title'].' - '.$current_thread['thread_title']." <br />\n";
  4084. $email_body .= get_lang('Course').': '.$_course['name'].' - ['.$_course['official_code']."] <br />\n";
  4085. $email_body .= get_lang('YouWantedToStayInformed')."<br />\n";
  4086. $email_body .= get_lang(
  4087. 'ThreadCanBeFoundHere'
  4088. ).': <br /> <a href="'.$thread_link.'">'.$thread_link."</a>\n";
  4089. MessageManager::send_message(
  4090. $value['user_id'],
  4091. $subject,
  4092. $email_body,
  4093. null,
  4094. null,
  4095. null,
  4096. null,
  4097. null,
  4098. null,
  4099. $sender_id
  4100. );
  4101. }
  4102. }
  4103. }
  4104. }
  4105. /**
  4106. * Get all the notification subscriptions of the user
  4107. * = which forums and which threads does the user wants to be informed of when a new
  4108. * post is added to this thread
  4109. *
  4110. * @param integer $user_id the user_id of a user (default = 0 => the current user)
  4111. * @param boolean $force force get the notification subscriptions (even if the information is already in the session
  4112. * @return array returns
  4113. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
  4114. * @version May 2008, dokeos 1.8.5
  4115. * @since May 2008, dokeos 1.8.5
  4116. */
  4117. function get_notifications_of_user($user_id = 0, $force = false)
  4118. {
  4119. // Database table definition
  4120. $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
  4121. $course_id = api_get_course_int_id();
  4122. if (empty($course_id) || $course_id == -1) {
  4123. return null;
  4124. }
  4125. if ($user_id == 0) {
  4126. $user_id = api_get_user_id();
  4127. }
  4128. if (!isset($_SESSION['forum_notification']) || $_SESSION['forum_notification']['course'] != $course_id || $force = true) {
  4129. $_SESSION['forum_notification']['course'] = $course_id;
  4130. $sql = "SELECT * FROM $table_notification WHERE c_id = $course_id AND user_id='".Database::escape_string(
  4131. $user_id
  4132. )."'";
  4133. $result = Database::query($sql);
  4134. while ($row = Database::fetch_array($result)) {
  4135. if (!is_null($row['forum_id'])) {
  4136. $_SESSION['forum_notification']['forum'][] = $row['forum_id'];
  4137. }
  4138. if (!is_null($row['thread_id'])) {
  4139. $_SESSION['forum_notification']['thread'][] = $row['thread_id'];
  4140. }
  4141. }
  4142. }
  4143. }
  4144. /**
  4145. * This function counts the number of post inside a thread
  4146. * @param int Thread ID
  4147. * @return int the number of post inside a thread
  4148. * @author Jhon Hinojosa <jhon.hinojosa@dokeos.com>,
  4149. * @version octubre 2008, dokeos 1.8
  4150. */
  4151. function count_number_of_post_in_thread($thread_id)
  4152. {
  4153. $table_posts = Database :: get_course_table(TABLE_FORUM_POST);
  4154. $course_id = api_get_course_int_id();
  4155. if (empty($course_id)) {
  4156. return 0;
  4157. }
  4158. $sql = "SELECT * FROM $table_posts WHERE c_id = $course_id AND thread_id='".Database::escape_string(
  4159. $thread_id
  4160. )."' ";
  4161. $result = Database::query($sql);
  4162. return count(Database::store_result($result));
  4163. }
  4164. /**
  4165. * This function counts the number of post inside a thread user
  4166. * @param int thread ID
  4167. * @param int user ID
  4168. * @return int the number of post inside a thread user
  4169. */
  4170. function count_number_of_post_for_user_thread($thread_id, $user_id)
  4171. {
  4172. $table_posts = Database::get_course_table(TABLE_FORUM_POST);
  4173. $course_id = api_get_course_int_id();
  4174. $sql = "SELECT count(*) as count FROM $table_posts
  4175. WHERE c_id = $course_id AND
  4176. thread_id=".Database::escape_string($thread_id)." AND
  4177. poster_id = ".Database::escape_string($user_id)." AND visible = 1 ";
  4178. $result = Database::query($sql);
  4179. $count = 0;
  4180. if (Database::num_rows($result) > 0) {
  4181. $count = Database::fetch_array($result);
  4182. $count = $count['count'];
  4183. }
  4184. return $count;
  4185. }
  4186. /**
  4187. * This function counts the number of user register in course
  4188. * @param int Course ID
  4189. * @return int the number of user register in course
  4190. * @author Jhon Hinojosa <jhon.hinojosa@dokeos.com>,
  4191. * @version octubre 2008, dokeos 1.8
  4192. */
  4193. function count_number_of_user_in_course($course_id)
  4194. {
  4195. $table_course_rel_user = Database::get_main_table('course_rel_user');
  4196. $sql = "SELECT * FROM $table_course_rel_user WHERE course_code ='".Database::escape_string($course_id)."' ";
  4197. $result = Database::query($sql);
  4198. return count(Database::store_result($result));
  4199. }
  4200. /**
  4201. * This function retrieves information of statistical
  4202. * @param int Thread ID
  4203. * @param int User ID
  4204. * @param int Course ID
  4205. * @return array the information of statistical
  4206. * @author Jhon Hinojosa <jhon.hinojosa@dokeos.com>,
  4207. * @version octubre 2008, dokeos 1.8
  4208. */
  4209. function get_statistical_information($thread_id, $user_id, $course_id)
  4210. {
  4211. $stadistic = array();
  4212. $stadistic['user_course'] = count_number_of_user_in_course($course_id);
  4213. $stadistic['post'] = count_number_of_post_in_thread($thread_id);
  4214. $stadistic['user_post'] = count_number_of_post_for_user_thread($thread_id, $user_id);
  4215. //$stadistic['average'] = get_average_of_thread_post_user();
  4216. return $stadistic;
  4217. }
  4218. /**
  4219. * This function return the posts inside a thread from a given user
  4220. * @param course code
  4221. * @param int Thread ID
  4222. * @param int User ID
  4223. * @return int the number of post inside a thread
  4224. * @author Jhon Hinojosa <jhon.hinojosa@dokeos.com>,
  4225. * @version octubre 2008, dokeos 1.8
  4226. */
  4227. function get_thread_user_post($course_code, $thread_id, $user_id)
  4228. {
  4229. $table_posts = Database::get_course_table(TABLE_FORUM_POST);
  4230. $table_users = Database::get_main_table(TABLE_MAIN_USER);
  4231. $thread_id = intval($thread_id);
  4232. $user_id = intval($user_id);
  4233. $course_info = api_get_user_info($course_code);
  4234. $course_id = $course_info['real_id'];
  4235. if (empty($course_id)) {
  4236. $course_id = api_get_course_int_id();
  4237. }
  4238. $sql = "SELECT * FROM $table_posts posts
  4239. LEFT JOIN $table_users users
  4240. ON posts.poster_id=users.user_id
  4241. WHERE
  4242. posts.c_id = $course_id AND
  4243. posts.thread_id='$thread_id'
  4244. AND posts.poster_id='$user_id'
  4245. ORDER BY posts.post_id ASC";
  4246. $result = Database::query($sql);
  4247. $post_list = array();
  4248. while ($row = Database::fetch_array($result)) {
  4249. $row['status'] = '1';
  4250. $post_list[] = $row;
  4251. $sql = "SELECT * FROM $table_posts posts
  4252. LEFT JOIN $table_users users
  4253. ON posts.poster_id=users.user_id
  4254. WHERE
  4255. posts.c_id = $course_id AND
  4256. posts.thread_id='$thread_id'
  4257. AND posts.post_parent_id='".$row['post_id']."'
  4258. ORDER BY posts.post_id ASC";
  4259. $result2 = Database::query($sql);
  4260. while ($row2 = Database::fetch_array($result2)) {
  4261. $row2['status'] = '0';
  4262. $post_list[] = $row2;
  4263. }
  4264. }
  4265. return $post_list;
  4266. }
  4267. /**
  4268. * This function get the name of an thread by id
  4269. * @param int thread_id
  4270. * @return String
  4271. * @author Christian Fasanando
  4272. * @author Julio Montoya <gugli100@gmail.com> Adding security
  4273. */
  4274. function get_name_thread_by_id($thread_id)
  4275. {
  4276. $t_forum_thread = Database::get_course_table(TABLE_FORUM_THREAD);
  4277. $course_id = api_get_course_int_id();
  4278. $sql = "SELECT thread_title FROM ".$t_forum_thread." WHERE c_id = $course_id AND thread_id = '".intval(
  4279. $thread_id
  4280. )."' ";
  4281. $result = Database::query($sql);
  4282. $row = Database::fetch_array($result);
  4283. return $row[0];
  4284. }
  4285. /**
  4286. * This function gets all the post written by an user
  4287. * @param int user id
  4288. * @param string db course name
  4289. * @return string
  4290. */
  4291. function get_all_post_from_user($user_id, $course_code)
  4292. {
  4293. $j = 0;
  4294. $forums = get_forums('', $course_code);
  4295. krsort($forums);
  4296. $forum_results = '';
  4297. foreach ($forums as $forum) {
  4298. if ($forum['visibility'] == 0) {
  4299. continue;
  4300. }
  4301. if ($j <= 4) {
  4302. $threads = get_threads($forum['forum_id'], $course_code);
  4303. if (is_array($threads)) {
  4304. $i = 0;
  4305. $hand_forums = '';
  4306. $post_counter = 0;
  4307. foreach ($threads as $thread) {
  4308. if ($thread['visibility'] == 0) {
  4309. continue;
  4310. }
  4311. if ($i <= 4) {
  4312. $post_list = get_thread_user_post_limit($course_code, $thread['thread_id'], $user_id, 1);
  4313. $post_counter = count($post_list);
  4314. if (is_array($post_list) && count($post_list) > 0) {
  4315. $hand_forums .= '<div id="social-thread">';
  4316. $hand_forums .= Display::return_icon(
  4317. 'thread.png',
  4318. get_lang('Thread'),
  4319. '',
  4320. ICON_SIZE_MEDIUM
  4321. );
  4322. $hand_forums .= '&nbsp;'.Security::remove_XSS($thread['thread_title'], STUDENT);
  4323. $hand_forums .= '</div>';
  4324. foreach ($post_list as $posts) {
  4325. $hand_forums .= '<div id="social-post">';
  4326. $hand_forums .= '<strong>'.Security::remove_XSS(
  4327. $posts['post_title'],
  4328. STUDENT
  4329. ).'</strong>';
  4330. $hand_forums .= '<br / >';
  4331. $hand_forums .= Security::remove_XSS($posts['post_text'], STUDENT);
  4332. $hand_forums .= '</div>';
  4333. $hand_forums .= '<br / >';
  4334. }
  4335. }
  4336. }
  4337. $i++;
  4338. }
  4339. $forum_results .= '<div id="social-forum">';
  4340. $forum_results .= '<div class="clear"></div><br />';
  4341. $forum_results .= '<div id="social-forum-title">'.
  4342. Display::return_icon('forum.gif', get_lang('Forum')).'&nbsp;'.Security::remove_XSS(
  4343. $forum['forum_title'],
  4344. STUDENT
  4345. ).
  4346. '<div style="float:right;margin-top:-35px">
  4347. <a href="../forum/viewforum.php?cidReq='.$course_code.'&amp;gidReq=&amp;forum='.$forum['forum_id'].' " >'.get_lang(
  4348. 'SeeForum'
  4349. ).'</a>
  4350. </div></div>';
  4351. $forum_results .= '<br / >';
  4352. if ($post_counter > 0) {
  4353. $forum_results .= $hand_forums;
  4354. }
  4355. $forum_results .= '</div>';
  4356. }
  4357. $j++;
  4358. }
  4359. }
  4360. return $forum_results;
  4361. }
  4362. /**
  4363. * @param string
  4364. * @param int
  4365. * @param int
  4366. * @param int
  4367. * @return void
  4368. */
  4369. function get_thread_user_post_limit($course_code, $thread_id, $user_id, $limit = 10)
  4370. {
  4371. $table_posts = Database::get_course_table(TABLE_FORUM_POST);
  4372. $table_users = Database::get_main_table(TABLE_MAIN_USER);
  4373. $course_info = api_get_course_info($course_code);
  4374. $course_id = $course_info['real_id'];
  4375. $sql = "SELECT * FROM $table_posts posts
  4376. LEFT JOIN $table_users users
  4377. ON posts.poster_id=users.user_id
  4378. WHERE
  4379. posts.c_id = $course_id AND
  4380. posts.thread_id='".Database::escape_string($thread_id)."'
  4381. AND posts.poster_id='".Database::escape_string($user_id)."'
  4382. ORDER BY posts.post_id DESC LIMIT $limit ";
  4383. $result = Database::query($sql);
  4384. while ($row = Database::fetch_array($result)) {
  4385. $row['status'] = '1';
  4386. $post_list[] = $row;
  4387. }
  4388. return $post_list;
  4389. }
  4390. /**
  4391. * This function builds an array of all the posts in a given thread where the key of the array is the post_id
  4392. * It also adds an element children to the array which itself is an array that contains all the id's of the first-level children
  4393. * @return an array containing all the information on the posts of a thread
  4394. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  4395. */
  4396. function calculate_children($rows)
  4397. {
  4398. $sorted_rows = array(0 => array());
  4399. if (!empty($rows)) {
  4400. foreach ($rows as $row) {
  4401. $rows_with_children[$row['post_id']] = $row;
  4402. $rows_with_children[$row['post_parent_id']]['children'][] = $row['post_id'];
  4403. }
  4404. $rows = $rows_with_children;
  4405. _phorum_recursive_sort($rows, $sorted_rows);
  4406. unset($sorted_rows[0]);
  4407. }
  4408. return $sorted_rows;
  4409. }
  4410. function _phorum_recursive_sort($rows, &$threads, $seed = 0, $indent = 0)
  4411. {
  4412. if ($seed > 0) {
  4413. $threads[$rows[$seed]['post_id']] = $rows[$seed];
  4414. $threads[$rows[$seed]['post_id']]['indent_cnt'] = $indent;
  4415. $indent++;
  4416. }
  4417. if (isset($rows[$seed]['children'])) {
  4418. foreach ($rows[$seed]['children'] as $child) {
  4419. _phorum_recursive_sort($rows, $threads, $child, $indent);
  4420. }
  4421. }
  4422. }