forumfunction.inc.php 228 KB

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