forumfunction.inc.php 227 KB

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