forumfunction.inc.php 232 KB

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