forumfunction.inc.php 231 KB

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