forumfunction.inc.php 220 KB

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