forumfunction.inc.php 227 KB

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