api.lib.php 297 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CoreBundle\Entity\AccessUrl;
  4. use Chamilo\CoreBundle\Entity\Course;
  5. use Chamilo\CoreBundle\Entity\Session as SessionEntity;
  6. use Chamilo\CoreBundle\Entity\SettingsCurrent;
  7. use Chamilo\CoreBundle\Framework\Container;
  8. use Chamilo\CourseBundle\Entity\CGroupInfo;
  9. use Chamilo\CourseBundle\Entity\CItemProperty;
  10. use Chamilo\ThemeBundle\Controller\ExceptionController;
  11. use Chamilo\UserBundle\Entity\User;
  12. use ChamiloSession as Session;
  13. use Symfony\Component\Debug\Exception\FlattenException;
  14. use Symfony\Component\Finder\Finder;
  15. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  16. /**
  17. * This is a code library for Chamilo.
  18. * It is included by default in every Chamilo file (through including the global.inc.php)
  19. * This library is in process of being transferred to src/Chamilo/CoreBundle/Component/Utils/ChamiloApi.
  20. * Whenever a function is transferred to the ChamiloApi class, the places where it is used should include
  21. * the "use Chamilo\CoreBundle\Component\Utils\ChamiloApi;" statement.
  22. */
  23. // PHP version requirement.
  24. define('REQUIRED_PHP_VERSION', '7.2');
  25. define('REQUIRED_MIN_MEMORY_LIMIT', '128');
  26. define('REQUIRED_MIN_UPLOAD_MAX_FILESIZE', '10');
  27. define('REQUIRED_MIN_POST_MAX_SIZE', '10');
  28. // USER STATUS CONSTANTS
  29. /** global status of a user: student */
  30. define('STUDENT', 5);
  31. /** global status of a user: course manager */
  32. define('COURSEMANAGER', 1);
  33. /** global status of a user: session admin */
  34. define('SESSIONADMIN', 3);
  35. /** global status of a user: human ressource manager */
  36. define('DRH', 4);
  37. /** global status of a user: human ressource manager */
  38. define('ANONYMOUS', 6);
  39. /** global status of a user: low security, necessary for inserting data from
  40. * the teacher through HTMLPurifier */
  41. define('COURSEMANAGERLOWSECURITY', 10);
  42. // Soft user status
  43. define('PLATFORM_ADMIN', 11);
  44. define('SESSION_COURSE_COACH', 12);
  45. define('SESSION_GENERAL_COACH', 13);
  46. define('COURSE_STUDENT', 14); //student subscribed in a course
  47. define('SESSION_STUDENT', 15); //student subscribed in a session course
  48. define('COURSE_TUTOR', 16); // student is tutor of a course (NOT in session)
  49. define('STUDENT_BOSS', 17); // student is boss
  50. define('INVITEE', 20);
  51. define('HRM_REQUEST', 21); //HRM has request for vinculation with user
  52. // Table of status
  53. $_status_list[COURSEMANAGER] = 'teacher'; // 1
  54. $_status_list[SESSIONADMIN] = 'session_admin'; // 3
  55. $_status_list[DRH] = 'drh'; // 4
  56. $_status_list[STUDENT] = 'user'; // 5
  57. $_status_list[ANONYMOUS] = 'anonymous'; // 6
  58. $_status_list[INVITEE] = 'invited'; // 20
  59. // COURSE VISIBILITY CONSTANTS
  60. /** only visible for course admin */
  61. define('COURSE_VISIBILITY_CLOSED', 0);
  62. /** only visible for users registered in the course */
  63. define('COURSE_VISIBILITY_REGISTERED', 1);
  64. /** Open for all registered users on the platform */
  65. define('COURSE_VISIBILITY_OPEN_PLATFORM', 2);
  66. /** Open for the whole world */
  67. define('COURSE_VISIBILITY_OPEN_WORLD', 3);
  68. /** Invisible to all except admin */
  69. define('COURSE_VISIBILITY_HIDDEN', 4);
  70. define('COURSE_REQUEST_PENDING', 0);
  71. define('COURSE_REQUEST_ACCEPTED', 1);
  72. define('COURSE_REQUEST_REJECTED', 2);
  73. define('DELETE_ACTION_ENABLED', false);
  74. // EMAIL SENDING RECIPIENT CONSTANTS
  75. define('SEND_EMAIL_EVERYONE', 1);
  76. define('SEND_EMAIL_STUDENTS', 2);
  77. define('SEND_EMAIL_TEACHERS', 3);
  78. // SESSION VISIBILITY CONSTANTS
  79. define('SESSION_VISIBLE_READ_ONLY', 1);
  80. define('SESSION_VISIBLE', 2);
  81. define('SESSION_INVISIBLE', 3); // not available
  82. define('SESSION_AVAILABLE', 4);
  83. define('SESSION_LINK_TARGET', '_self');
  84. define('SUBSCRIBE_ALLOWED', 1);
  85. define('SUBSCRIBE_NOT_ALLOWED', 0);
  86. define('UNSUBSCRIBE_ALLOWED', 1);
  87. define('UNSUBSCRIBE_NOT_ALLOWED', 0);
  88. // SURVEY VISIBILITY CONSTANTS
  89. define('SURVEY_VISIBLE_TUTOR', 0);
  90. define('SURVEY_VISIBLE_TUTOR_STUDENT', 1);
  91. define('SURVEY_VISIBLE_PUBLIC', 2);
  92. // CONSTANTS defining all tools, using the english version
  93. /* When you add a new tool you must add it into function api_get_tools_lists() too */
  94. define('TOOL_DOCUMENT', 'document');
  95. define('TOOL_LP_FINAL_ITEM', 'final_item');
  96. define('TOOL_READOUT_TEXT', 'readout_text');
  97. define('TOOL_THUMBNAIL', 'thumbnail');
  98. define('TOOL_HOTPOTATOES', 'hotpotatoes');
  99. define('TOOL_CALENDAR_EVENT', 'calendar_event');
  100. define('TOOL_LINK', 'link');
  101. define('TOOL_LINK_CATEGORY', 'link_category');
  102. define('TOOL_COURSE_DESCRIPTION', 'course_description');
  103. define('TOOL_SEARCH', 'search');
  104. define('TOOL_LEARNPATH', 'learnpath');
  105. define('TOOL_LEARNPATH_CATEGORY', 'learnpath_category');
  106. define('TOOL_AGENDA', 'agenda');
  107. define('TOOL_ANNOUNCEMENT', 'announcement');
  108. define('TOOL_FORUM', 'forum');
  109. define('TOOL_FORUM_CATEGORY', 'forum_category');
  110. define('TOOL_FORUM_THREAD', 'forum_thread');
  111. define('TOOL_FORUM_POST', 'forum_post');
  112. define('TOOL_FORUM_ATTACH', 'forum_attachment');
  113. define('TOOL_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
  114. define('TOOL_THREAD', 'thread');
  115. define('TOOL_POST', 'post');
  116. define('TOOL_DROPBOX', 'dropbox');
  117. define('TOOL_QUIZ', 'quiz');
  118. define('TOOL_TEST_CATEGORY', 'test_category');
  119. define('TOOL_USER', 'user');
  120. define('TOOL_GROUP', 'group');
  121. define('TOOL_BLOGS', 'blog_management');
  122. define('TOOL_CHAT', 'chat');
  123. define('TOOL_STUDENTPUBLICATION', 'student_publication');
  124. define('TOOL_TRACKING', 'tracking');
  125. define('TOOL_HOMEPAGE_LINK', 'homepage_link');
  126. define('TOOL_COURSE_SETTING', 'course_setting');
  127. define('TOOL_BACKUP', 'backup');
  128. define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
  129. define('TOOL_RECYCLE_COURSE', 'recycle_course');
  130. define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
  131. define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
  132. define('TOOL_UPLOAD', 'file_upload');
  133. define('TOOL_COURSE_MAINTENANCE', 'course_maintenance');
  134. define('TOOL_SURVEY', 'survey');
  135. define('TOOL_WIKI', 'wiki');
  136. define('TOOL_GLOSSARY', 'glossary');
  137. define('TOOL_GRADEBOOK', 'gradebook');
  138. define('TOOL_NOTEBOOK', 'notebook');
  139. define('TOOL_ATTENDANCE', 'attendance');
  140. define('TOOL_COURSE_PROGRESS', 'course_progress');
  141. define('TOOL_PORTFOLIO', 'portfolio');
  142. define('TOOL_PLAGIARISM', 'compilatio');
  143. // CONSTANTS defining Chamilo interface sections
  144. define('SECTION_CAMPUS', 'mycampus');
  145. define('SECTION_COURSES', 'mycourses');
  146. define('SECTION_CATALOG', 'catalog');
  147. define('SECTION_MYPROFILE', 'myprofile');
  148. define('SECTION_MYAGENDA', 'myagenda');
  149. define('SECTION_COURSE_ADMIN', 'course_admin');
  150. define('SECTION_PLATFORM_ADMIN', 'platform_admin');
  151. define('SECTION_MYGRADEBOOK', 'mygradebook');
  152. define('SECTION_TRACKING', 'session_my_space');
  153. define('SECTION_SOCIAL', 'social-network');
  154. define('SECTION_DASHBOARD', 'dashboard');
  155. define('SECTION_REPORTS', 'reports');
  156. define('SECTION_GLOBAL', 'global');
  157. define('SECTION_INCLUDE', 'include');
  158. // CONSTANT name for local authentication source
  159. define('PLATFORM_AUTH_SOURCE', 'platform');
  160. define('CAS_AUTH_SOURCE', 'cas');
  161. define('LDAP_AUTH_SOURCE', 'extldap');
  162. // CONSTANT defining the default HotPotatoes files directory
  163. define('DIR_HOTPOTATOES', '/HotPotatoes_files');
  164. // event logs types
  165. define('LOG_COURSE_DELETE', 'course_deleted');
  166. define('LOG_COURSE_CREATE', 'course_created');
  167. // @todo replace 'soc_gr' with social_group
  168. define('LOG_GROUP_PORTAL_CREATED', 'soc_gr_created');
  169. define('LOG_GROUP_PORTAL_UPDATED', 'soc_gr_updated');
  170. define('LOG_GROUP_PORTAL_DELETED', 'soc_gr_deleted');
  171. define('LOG_GROUP_PORTAL_USER_DELETE_ALL', 'soc_gr_delete_users');
  172. define('LOG_GROUP_PORTAL_ID', 'soc_gr_portal_id');
  173. define('LOG_GROUP_PORTAL_REL_USER_ARRAY', 'soc_gr_user_array');
  174. define('LOG_GROUP_PORTAL_USER_SUBSCRIBED', 'soc_gr_u_subs');
  175. define('LOG_GROUP_PORTAL_USER_UNSUBSCRIBED', 'soc_gr_u_unsubs');
  176. define('LOG_GROUP_PORTAL_USER_UPDATE_ROLE', 'soc_gr_update_role');
  177. define('LOG_USER_DELETE', 'user_deleted');
  178. define('LOG_USER_CREATE', 'user_created');
  179. define('LOG_USER_ENABLE', 'user_enable');
  180. define('LOG_USER_DISABLE', 'user_disable');
  181. define('LOG_USER_ANONYMIZE', 'user_anonymized');
  182. define('LOG_USER_FIELD_CREATE', 'user_field_created');
  183. define('LOG_USER_FIELD_DELETE', 'user_field_deleted');
  184. define('LOG_SESSION_CREATE', 'session_created');
  185. define('LOG_SESSION_DELETE', 'session_deleted');
  186. define('LOG_SESSION_ADD_USER_COURSE', 'session_add_user_course');
  187. define('LOG_SESSION_DELETE_USER_COURSE', 'session_delete_user_course');
  188. define('LOG_SESSION_ADD_USER', 'session_add_user');
  189. define('LOG_SESSION_DELETE_USER', 'session_delete_user');
  190. define('LOG_SESSION_ADD_COURSE', 'session_add_course');
  191. define('LOG_SESSION_DELETE_COURSE', 'session_delete_course');
  192. define('LOG_SESSION_CATEGORY_CREATE', 'session_cat_created'); //changed in 1.9.8
  193. define('LOG_SESSION_CATEGORY_DELETE', 'session_cat_deleted'); //changed in 1.9.8
  194. define('LOG_CONFIGURATION_SETTINGS_CHANGE', 'settings_changed');
  195. define('LOG_PLATFORM_LANGUAGE_CHANGE', 'platform_lng_changed'); //changed in 1.9.8
  196. define('LOG_SUBSCRIBE_USER_TO_COURSE', 'user_subscribed');
  197. define('LOG_UNSUBSCRIBE_USER_FROM_COURSE', 'user_unsubscribed');
  198. define('LOG_ATTEMPTED_FORCED_LOGIN', 'attempted_forced_login');
  199. define('LOG_HOMEPAGE_CHANGED', 'homepage_changed');
  200. define('LOG_PROMOTION_CREATE', 'promotion_created');
  201. define('LOG_PROMOTION_DELETE', 'promotion_deleted');
  202. define('LOG_CAREER_CREATE', 'career_created');
  203. define('LOG_CAREER_DELETE', 'career_deleted');
  204. define('LOG_USER_PERSONAL_DOC_DELETED', 'user_doc_deleted');
  205. define('LOG_WIKI_ACCESS', 'wiki_page_view');
  206. // All results from an exercise
  207. define('LOG_EXERCISE_RESULT_DELETE', 'exe_result_deleted');
  208. // Logs only the one attempt
  209. define('LOG_EXERCISE_ATTEMPT_DELETE', 'exe_attempt_deleted');
  210. define('LOG_LP_ATTEMPT_DELETE', 'lp_attempt_deleted');
  211. define('LOG_QUESTION_RESULT_DELETE', 'qst_attempt_deleted');
  212. define('LOG_MY_FOLDER_CREATE', 'my_folder_created');
  213. define('LOG_MY_FOLDER_CHANGE', 'my_folder_changed');
  214. define('LOG_MY_FOLDER_DELETE', 'my_folder_deleted');
  215. define('LOG_MY_FOLDER_COPY', 'my_folder_copied');
  216. define('LOG_MY_FOLDER_CUT', 'my_folder_cut');
  217. define('LOG_MY_FOLDER_PASTE', 'my_folder_pasted');
  218. define('LOG_MY_FOLDER_UPLOAD', 'my_folder_uploaded');
  219. // Event logs data types (max 20 chars)
  220. define('LOG_COURSE_CODE', 'course_code');
  221. define('LOG_COURSE_ID', 'course_id');
  222. define('LOG_USER_ID', 'user_id');
  223. define('LOG_USER_OBJECT', 'user_object');
  224. define('LOG_USER_FIELD_VARIABLE', 'user_field_variable');
  225. define('LOG_SESSION_ID', 'session_id');
  226. define('LOG_QUESTION_ID', 'question_id');
  227. define('LOG_SESSION_CATEGORY_ID', 'session_category_id');
  228. define('LOG_CONFIGURATION_SETTINGS_CATEGORY', 'settings_category');
  229. define('LOG_CONFIGURATION_SETTINGS_VARIABLE', 'settings_variable');
  230. define('LOG_PLATFORM_LANGUAGE', 'default_platform_language');
  231. define('LOG_CAREER_ID', 'career_id');
  232. define('LOG_PROMOTION_ID', 'promotion_id');
  233. define('LOG_GRADEBOOK_LOCKED', 'gradebook_locked');
  234. define('LOG_GRADEBOOK_UNLOCKED', 'gradebook_unlocked');
  235. define('LOG_GRADEBOOK_ID', 'gradebook_id');
  236. define('LOG_WIKI_PAGE_ID', 'wiki_page_id');
  237. define('LOG_EXERCISE_ID', 'exercise_id');
  238. define('LOG_EXERCISE_AND_USER_ID', 'exercise_and_user_id');
  239. define('LOG_LP_ID', 'lp_id');
  240. define('LOG_EXERCISE_ATTEMPT_QUESTION_ID', 'exercise_a_q_id');
  241. define('LOG_EXERCISE_ATTEMPT', 'exe_id');
  242. define('LOG_WORK_DIR_DELETE', 'work_dir_delete');
  243. define('LOG_WORK_FILE_DELETE', 'work_file_delete');
  244. define('LOG_WORK_DATA', 'work_data_array');
  245. define('LOG_MY_FOLDER_PATH', 'path');
  246. define('LOG_MY_FOLDER_NEW_PATH', 'new_path');
  247. define('LOG_TERM_CONDITION_ACCEPTED', 'term_condition_accepted');
  248. define('LOG_USER_CONFIRMED_EMAIL', 'user_confirmed_email');
  249. define('LOG_USER_REMOVED_LEGAL_ACCEPT', 'user_removed_legal_accept');
  250. define('LOG_USER_DELETE_ACCOUNT_REQUEST', 'user_delete_account_request');
  251. define('LOG_QUESTION_CREATED', 'question_created');
  252. define('LOG_QUESTION_UPDATED', 'question_updated');
  253. define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.-]/');
  254. //used when login_is_email setting is true
  255. define('USERNAME_PURIFIER_MAIL', '/[^0-9A-Za-z_\.@]/');
  256. define('USERNAME_PURIFIER_SHALLOW', '/\s/');
  257. // This constant is a result of Windows OS detection, it has a boolean value:
  258. // true whether the server runs on Windows OS, false otherwise.
  259. define('IS_WINDOWS_OS', api_is_windows_os());
  260. // iconv extension, for PHP5 on Windows it is installed by default.
  261. define('ICONV_INSTALLED', function_exists('iconv'));
  262. define('MBSTRING_INSTALLED', function_exists('mb_strlen')); // mbstring extension.
  263. // Patterns for processing paths. Examples.
  264. define('REPEATED_SLASHES_PURIFIER', '/\/{2,}/'); // $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
  265. define('VALID_WEB_PATH', '/https?:\/\/[^\/]*(\/.*)?/i'); // $is_valid_path = preg_match(VALID_WEB_PATH, $path);
  266. // $new_path = preg_replace(VALID_WEB_SERVER_BASE, $new_base, $path);
  267. define('VALID_WEB_SERVER_BASE', '/https?:\/\/[^\/]*/i');
  268. // Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
  269. // basic (leaf elements)
  270. define('REL_CODE_PATH', 'REL_CODE_PATH');
  271. define('REL_COURSE_PATH', 'REL_COURSE_PATH');
  272. define('REL_HOME_PATH', 'REL_HOME_PATH');
  273. // Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
  274. define('WEB_PATH', 'WEB_PATH');
  275. define('SYS_PATH', 'SYS_PATH');
  276. define('SYS_APP_PATH', 'SYS_APP_PATH');
  277. define('SYS_UPLOAD_PATH', 'SYS_UPLOAD_PATH');
  278. define('WEB_UPLOAD_PATH', 'WEB_UPLOAD_PATH');
  279. define('REL_PATH', 'REL_PATH');
  280. define('WEB_COURSE_PATH', 'WEB_COURSE_PATH');
  281. define('SYS_COURSE_PATH', 'SYS_COURSE_PATH');
  282. define('WEB_CODE_PATH', 'WEB_CODE_PATH');
  283. define('SYS_CODE_PATH', 'SYS_CODE_PATH');
  284. define('SYS_LANG_PATH', 'SYS_LANG_PATH');
  285. define('WEB_IMG_PATH', 'WEB_IMG_PATH');
  286. define('WEB_CSS_PATH', 'WEB_CSS_PATH');
  287. define('WEB_PUBLIC_PATH', 'WEB_PUBLIC_PATH');
  288. define('SYS_CSS_PATH', 'SYS_CSS_PATH');
  289. define('SYS_PLUGIN_PATH', 'SYS_PLUGIN_PATH');
  290. define('WEB_PLUGIN_PATH', 'WEB_PLUGIN_PATH');
  291. define('WEB_PLUGIN_ASSET_PATH', 'WEB_PLUGIN_ASSET_PATH');
  292. define('SYS_ARCHIVE_PATH', 'SYS_ARCHIVE_PATH');
  293. define('WEB_ARCHIVE_PATH', 'WEB_ARCHIVE_PATH');
  294. define('SYS_INC_PATH', 'SYS_INC_PATH');
  295. define('LIBRARY_PATH', 'LIBRARY_PATH');
  296. define('CONFIGURATION_PATH', 'CONFIGURATION_PATH');
  297. define('WEB_LIBRARY_PATH', 'WEB_LIBRARY_PATH');
  298. define('WEB_LIBRARY_JS_PATH', 'WEB_LIBRARY_JS_PATH');
  299. define('WEB_AJAX_PATH', 'WEB_AJAX_PATH');
  300. define('SYS_TEST_PATH', 'SYS_TEST_PATH');
  301. define('WEB_TEMPLATE_PATH', 'WEB_TEMPLATE_PATH');
  302. define('SYS_TEMPLATE_PATH', 'SYS_TEMPLATE_PATH');
  303. define('SYS_PUBLIC_PATH', 'SYS_PUBLIC_PATH');
  304. define('SYS_HOME_PATH', 'SYS_HOME_PATH');
  305. define('WEB_HOME_PATH', 'WEB_HOME_PATH');
  306. define('WEB_FONTS_PATH', 'WEB_FONTS_PATH');
  307. define('SYS_FONTS_PATH', 'SYS_FONTS_PATH');
  308. // Relations type with Course manager
  309. define('COURSE_RELATION_TYPE_COURSE_MANAGER', 1);
  310. define('SESSION_RELATION_TYPE_COURSE_MANAGER', 1);
  311. // Relations type with Human resources manager
  312. define('COURSE_RELATION_TYPE_RRHH', 1);
  313. define('SESSION_RELATION_TYPE_RRHH', 1);
  314. //User image sizes
  315. define('USER_IMAGE_SIZE_ORIGINAL', 1);
  316. define('USER_IMAGE_SIZE_BIG', 2);
  317. define('USER_IMAGE_SIZE_MEDIUM', 3);
  318. define('USER_IMAGE_SIZE_SMALL', 4);
  319. // Relation type between users
  320. define('USER_UNKNOWN', 0);
  321. define('USER_RELATION_TYPE_UNKNOWN', 1);
  322. define('USER_RELATION_TYPE_PARENT', 2); // should be deprecated is useless
  323. define('USER_RELATION_TYPE_FRIEND', 3);
  324. define('USER_RELATION_TYPE_GOODFRIEND', 4); // should be deprecated is useless
  325. define('USER_RELATION_TYPE_ENEMY', 5); // should be deprecated is useless
  326. define('USER_RELATION_TYPE_DELETED', 6);
  327. define('USER_RELATION_TYPE_RRHH', 7);
  328. define('USER_RELATION_TYPE_BOSS', 8);
  329. define('USER_RELATION_TYPE_HRM_REQUEST', 9);
  330. // Gradebook link constants
  331. // Please do not change existing values, they are used in the database !
  332. define('GRADEBOOK_ITEM_LIMIT', 1000);
  333. define('LINK_EXERCISE', 1);
  334. define('LINK_DROPBOX', 2);
  335. define('LINK_STUDENTPUBLICATION', 3);
  336. define('LINK_LEARNPATH', 4);
  337. define('LINK_FORUM_THREAD', 5);
  338. //define('LINK_WORK',6);
  339. define('LINK_ATTENDANCE', 7);
  340. define('LINK_SURVEY', 8);
  341. define('LINK_HOTPOTATOES', 9);
  342. // Score display types constants
  343. define('SCORE_DIV', 1); // X / Y
  344. define('SCORE_PERCENT', 2); // XX %
  345. define('SCORE_DIV_PERCENT', 3); // X / Y (XX %)
  346. define('SCORE_AVERAGE', 4); // XX %
  347. define('SCORE_DECIMAL', 5); // 0.50 (X/Y)
  348. define('SCORE_BAR', 6); // Uses the Display::bar_progress function
  349. define('SCORE_SIMPLE', 7); // X
  350. define('SCORE_IGNORE_SPLIT', 8); // ??
  351. define('SCORE_DIV_PERCENT_WITH_CUSTOM', 9); // X / Y (XX %) - Good!
  352. define('SCORE_CUSTOM', 10); // Good!
  353. define('SCORE_DIV_SIMPLE_WITH_CUSTOM', 11); // X - Good!
  354. define('SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS', 12); // X - Good!
  355. define('SCORE_ONLY_SCORE', 13); // X - Good!
  356. define('SCORE_NUMERIC', 14);
  357. define('SCORE_BOTH', 1);
  358. define('SCORE_ONLY_DEFAULT', 2);
  359. define('SCORE_ONLY_CUSTOM', 3);
  360. // From display.lib.php
  361. define('MAX_LENGTH_BREADCRUMB', 100);
  362. define('ICON_SIZE_ATOM', 8);
  363. define('ICON_SIZE_TINY', 16);
  364. define('ICON_SIZE_SMALL', 22);
  365. define('ICON_SIZE_MEDIUM', 32);
  366. define('ICON_SIZE_LARGE', 48);
  367. define('ICON_SIZE_BIG', 64);
  368. define('ICON_SIZE_HUGE', 128);
  369. define('SHOW_TEXT_NEAR_ICONS', false);
  370. // Session catalog
  371. define('CATALOG_COURSES', 0);
  372. define('CATALOG_SESSIONS', 1);
  373. define('CATALOG_COURSES_SESSIONS', 2);
  374. // Hook type events, pre-process and post-process.
  375. // All means to be executed for both hook event types
  376. define('HOOK_EVENT_TYPE_PRE', 0);
  377. define('HOOK_EVENT_TYPE_POST', 1);
  378. define('HOOK_EVENT_TYPE_ALL', 10);
  379. define('CAREER_STATUS_ACTIVE', 1);
  380. define('CAREER_STATUS_INACTIVE', 0);
  381. define('PROMOTION_STATUS_ACTIVE', 1);
  382. define('PROMOTION_STATUS_INACTIVE', 0);
  383. // Group permissions
  384. define('GROUP_PERMISSION_OPEN', '1');
  385. define('GROUP_PERMISSION_CLOSED', '2');
  386. // Group user permissions
  387. define('GROUP_USER_PERMISSION_ADMIN', '1'); // the admin of a group
  388. define('GROUP_USER_PERMISSION_READER', '2'); // a normal user
  389. define('GROUP_USER_PERMISSION_PENDING_INVITATION', '3'); // When an admin/moderator invites a user
  390. define('GROUP_USER_PERMISSION_PENDING_INVITATION_SENT_BY_USER', '4'); // an user joins a group
  391. define('GROUP_USER_PERMISSION_MODERATOR', '5'); // a moderator
  392. define('GROUP_USER_PERMISSION_ANONYMOUS', '6'); // an anonymous user
  393. define('GROUP_USER_PERMISSION_HRM', '7'); // a human resources manager
  394. define('GROUP_IMAGE_SIZE_ORIGINAL', 1);
  395. define('GROUP_IMAGE_SIZE_BIG', 2);
  396. define('GROUP_IMAGE_SIZE_MEDIUM', 3);
  397. define('GROUP_IMAGE_SIZE_SMALL', 4);
  398. define('GROUP_TITLE_LENGTH', 50);
  399. // Exercise
  400. // @todo move into a class
  401. define('ALL_ON_ONE_PAGE', 1);
  402. define('ONE_PER_PAGE', 2);
  403. define('EXERCISE_FEEDBACK_TYPE_END', 0); //Feedback - show score and expected answers
  404. define('EXERCISE_FEEDBACK_TYPE_DIRECT', 1); //DirectFeedback - Do not show score nor answers
  405. define('EXERCISE_FEEDBACK_TYPE_EXAM', 2); // NoFeedback - Show score only
  406. define('EXERCISE_FEEDBACK_TYPE_POPUP', 3); // Popup BT#15827
  407. define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS', 0); //show score and expected answers
  408. define('RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS', 1); //Do not show score nor answers
  409. define('RESULT_DISABLE_SHOW_SCORE_ONLY', 2); //Show score only
  410. define('RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES', 3); //Show final score only with categories
  411. define('RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT', 4);
  412. define('RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK', 5);
  413. define('RESULT_DISABLE_RANKING', 6);
  414. define('RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER', 7);
  415. define('RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING', 8);
  416. define('EXERCISE_MAX_NAME_SIZE', 80);
  417. // Question types (edit next array as well when adding values)
  418. // @todo move into a class
  419. define('UNIQUE_ANSWER', 1);
  420. define('MULTIPLE_ANSWER', 2);
  421. define('FILL_IN_BLANKS', 3);
  422. define('MATCHING', 4);
  423. define('FREE_ANSWER', 5);
  424. define('HOT_SPOT', 6);
  425. define('HOT_SPOT_ORDER', 7);
  426. define('HOT_SPOT_DELINEATION', 8);
  427. define('MULTIPLE_ANSWER_COMBINATION', 9);
  428. define('UNIQUE_ANSWER_NO_OPTION', 10);
  429. define('MULTIPLE_ANSWER_TRUE_FALSE', 11);
  430. define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12);
  431. define('ORAL_EXPRESSION', 13);
  432. define('GLOBAL_MULTIPLE_ANSWER', 14);
  433. define('MEDIA_QUESTION', 15);
  434. define('CALCULATED_ANSWER', 16);
  435. define('UNIQUE_ANSWER_IMAGE', 17);
  436. define('DRAGGABLE', 18);
  437. define('MATCHING_DRAGGABLE', 19);
  438. define('ANNOTATION', 20);
  439. define('READING_COMPREHENSION', 21);
  440. define('MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY', 22);
  441. define('EXERCISE_CATEGORY_RANDOM_SHUFFLED', 1);
  442. define('EXERCISE_CATEGORY_RANDOM_ORDERED', 2);
  443. define('EXERCISE_CATEGORY_RANDOM_DISABLED', 0);
  444. // Question selection type
  445. define('EX_Q_SELECTION_ORDERED', 1);
  446. define('EX_Q_SELECTION_RANDOM', 2);
  447. define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_ORDERED', 3);
  448. define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED', 4);
  449. define('EX_Q_SELECTION_CATEGORIES_ORDERED_QUESTIONS_RANDOM', 5);
  450. define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM', 6);
  451. define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_ORDERED_NO_GROUPED', 7);
  452. define('EX_Q_SELECTION_CATEGORIES_RANDOM_QUESTIONS_RANDOM_NO_GROUPED', 8);
  453. define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_ORDERED', 9);
  454. define('EX_Q_SELECTION_CATEGORIES_ORDERED_BY_PARENT_QUESTIONS_RANDOM', 10);
  455. // Used to save the skill_rel_item table
  456. define('ITEM_TYPE_EXERCISE', 1);
  457. define('ITEM_TYPE_HOTPOTATOES', 2);
  458. define('ITEM_TYPE_LINK', 3);
  459. define('ITEM_TYPE_LEARNPATH', 4);
  460. define('ITEM_TYPE_GRADEBOOK', 5);
  461. define('ITEM_TYPE_STUDENT_PUBLICATION', 6);
  462. //define('ITEM_TYPE_FORUM', 7);
  463. define('ITEM_TYPE_ATTENDANCE', 8);
  464. define('ITEM_TYPE_SURVEY', 9);
  465. define('ITEM_TYPE_FORUM_THREAD', 10);
  466. // one big string with all question types, for the validator in pear/HTML/QuickForm/Rule/QuestionType
  467. define(
  468. 'QUESTION_TYPES',
  469. UNIQUE_ANSWER.':'.
  470. MULTIPLE_ANSWER.':'.
  471. FILL_IN_BLANKS.':'.
  472. MATCHING.':'.
  473. FREE_ANSWER.':'.
  474. HOT_SPOT.':'.
  475. HOT_SPOT_ORDER.':'.
  476. HOT_SPOT_DELINEATION.':'.
  477. MULTIPLE_ANSWER_COMBINATION.':'.
  478. UNIQUE_ANSWER_NO_OPTION.':'.
  479. MULTIPLE_ANSWER_TRUE_FALSE.':'.
  480. MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE.':'.
  481. ORAL_EXPRESSION.':'.
  482. GLOBAL_MULTIPLE_ANSWER.':'.
  483. MEDIA_QUESTION.':'.
  484. CALCULATED_ANSWER.':'.
  485. UNIQUE_ANSWER_IMAGE.':'.
  486. DRAGGABLE.':'.
  487. MATCHING_DRAGGABLE.':'.
  488. MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY.':'.
  489. ANNOTATION
  490. );
  491. //Some alias used in the QTI exports
  492. define('MCUA', 1);
  493. define('TF', 1);
  494. define('MCMA', 2);
  495. define('FIB', 3);
  496. // Skills
  497. define('SKILL_TYPE_REQUIREMENT', 'required');
  498. define('SKILL_TYPE_ACQUIRED', 'acquired');
  499. define('SKILL_TYPE_BOTH', 'both');
  500. // Message
  501. define('MESSAGE_STATUS_NEW', '0');
  502. define('MESSAGE_STATUS_UNREAD', '1');
  503. //2 ??
  504. define('MESSAGE_STATUS_DELETED', '3');
  505. define('MESSAGE_STATUS_OUTBOX', '4');
  506. define('MESSAGE_STATUS_INVITATION_PENDING', '5');
  507. define('MESSAGE_STATUS_INVITATION_ACCEPTED', '6');
  508. define('MESSAGE_STATUS_INVITATION_DENIED', '7');
  509. define('MESSAGE_STATUS_WALL', '8');
  510. define('MESSAGE_STATUS_WALL_DELETE', '9');
  511. define('MESSAGE_STATUS_WALL_POST', '10');
  512. define('MESSAGE_STATUS_CONVERSATION', '11');
  513. define('MESSAGE_STATUS_FORUM', '12');
  514. define('MESSAGE_STATUS_PROMOTED', '13');
  515. // Images
  516. define('IMAGE_WALL_SMALL_SIZE', 200);
  517. define('IMAGE_WALL_MEDIUM_SIZE', 500);
  518. define('IMAGE_WALL_BIG_SIZE', 2000);
  519. define('IMAGE_WALL_SMALL', 'small');
  520. define('IMAGE_WALL_MEDIUM', 'medium');
  521. define('IMAGE_WALL_BIG', 'big');
  522. // Social PLUGIN PLACES
  523. define('SOCIAL_LEFT_PLUGIN', 1);
  524. define('SOCIAL_CENTER_PLUGIN', 2);
  525. define('SOCIAL_RIGHT_PLUGIN', 3);
  526. define('CUT_GROUP_NAME', 50);
  527. /**
  528. * FormValidator Filter.
  529. */
  530. define('NO_HTML', 1);
  531. define('STUDENT_HTML', 2);
  532. define('TEACHER_HTML', 3);
  533. define('STUDENT_HTML_FULLPAGE', 4);
  534. define('TEACHER_HTML_FULLPAGE', 5);
  535. // Timeline
  536. define('TIMELINE_STATUS_ACTIVE', '1');
  537. define('TIMELINE_STATUS_INACTIVE', '2');
  538. // Event email template class
  539. define('EVENT_EMAIL_TEMPLATE_ACTIVE', 1);
  540. define('EVENT_EMAIL_TEMPLATE_INACTIVE', 0);
  541. // Course home
  542. define('SHORTCUTS_HORIZONTAL', 0);
  543. define('SHORTCUTS_VERTICAL', 1);
  544. // Image class
  545. define('IMAGE_PROCESSOR', 'gd'); // 'imagick' or 'gd' strings
  546. // Course copy
  547. define('FILE_SKIP', 1);
  548. define('FILE_RENAME', 2);
  549. define('FILE_OVERWRITE', 3);
  550. define('UTF8_CONVERT', false); //false by default
  551. define('DOCUMENT', 'file');
  552. define('FOLDER', 'folder');
  553. define('RESOURCE_ASSET', 'asset');
  554. define('RESOURCE_DOCUMENT', 'document');
  555. define('RESOURCE_GLOSSARY', 'glossary');
  556. define('RESOURCE_EVENT', 'calendar_event');
  557. define('RESOURCE_LINK', 'link');
  558. define('RESOURCE_COURSEDESCRIPTION', 'course_description');
  559. define('RESOURCE_LEARNPATH', 'learnpath');
  560. define('RESOURCE_LEARNPATH_CATEGORY', 'learnpath_category');
  561. define('RESOURCE_ANNOUNCEMENT', 'announcement');
  562. define('RESOURCE_FORUM', 'forum');
  563. define('RESOURCE_FORUMTOPIC', 'thread');
  564. define('RESOURCE_FORUMPOST', 'post');
  565. define('RESOURCE_QUIZ', 'quiz');
  566. define('RESOURCE_TEST_CATEGORY', 'test_category');
  567. define('RESOURCE_QUIZQUESTION', 'Exercise_Question');
  568. define('RESOURCE_TOOL_INTRO', 'Tool introduction');
  569. define('RESOURCE_LINKCATEGORY', 'Link_Category');
  570. define('RESOURCE_FORUMCATEGORY', 'Forum_Category');
  571. define('RESOURCE_SCORM', 'Scorm');
  572. define('RESOURCE_SURVEY', 'survey');
  573. define('RESOURCE_SURVEYQUESTION', 'survey_question');
  574. define('RESOURCE_SURVEYINVITATION', 'survey_invitation');
  575. define('RESOURCE_WIKI', 'wiki');
  576. define('RESOURCE_THEMATIC', 'thematic');
  577. define('RESOURCE_ATTENDANCE', 'attendance');
  578. define('RESOURCE_WORK', 'work');
  579. define('RESOURCE_SESSION_COURSE', 'session_course');
  580. define('RESOURCE_GRADEBOOK', 'gradebook');
  581. define('ADD_THEMATIC_PLAN', 6);
  582. // Max online users to show per page (whoisonline)
  583. define('MAX_ONLINE_USERS', 12);
  584. // Number of characters maximum to show in preview of course blog posts
  585. define('BLOG_MAX_PREVIEW_CHARS', 800);
  586. // HTML string to replace with a 'Read more...' link
  587. define('BLOG_PAGE_BREAK', '<div style="page-break-after: always"><span style="display: none;">&nbsp;</span></div>');
  588. // Make sure the CHAMILO_LOAD_WYSIWYG constant is defined
  589. // To remove CKeditor libs from HTML, set this constant to true before loading
  590. if (!defined('CHAMILO_LOAD_WYSIWYG')) {
  591. define('CHAMILO_LOAD_WYSIWYG', true);
  592. }
  593. /* Constants for course home */
  594. define('TOOL_PUBLIC', 'Public');
  595. define('TOOL_PUBLIC_BUT_HIDDEN', 'PublicButHide');
  596. define('TOOL_COURSE_ADMIN', 'courseAdmin');
  597. define('TOOL_PLATFORM_ADMIN', 'platformAdmin');
  598. define('TOOL_AUTHORING', 'toolauthoring');
  599. define('TOOL_INTERACTION', 'toolinteraction');
  600. define('TOOL_COURSE_PLUGIN', 'toolcourseplugin'); //all plugins that can be enabled in courses
  601. define('TOOL_ADMIN', 'tooladmin');
  602. define('TOOL_ADMIN_PLATFORM', 'tooladminplatform');
  603. define('TOOL_DRH', 'tool_drh');
  604. define('TOOL_STUDENT_VIEW', 'toolstudentview');
  605. define('TOOL_ADMIN_VISIBLE', 'tooladminvisible');
  606. /**
  607. * Returns a path to a certain resource within the Chamilo area, specifyed through a parameter.
  608. * Also, this function provides conversion between path types, in this case the input path points inside the Chamilo area too.
  609. *
  610. * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
  611. *
  612. * @param string $path (optional) A path which type is to be converted. Also, it may be a defined constant for a path.
  613. * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
  614. *
  615. * @return string the requested path or the converted path
  616. *
  617. *
  618. * Notes about the current behaviour model:
  619. * 1. Windows back-slashes are converted to slashes in the result.
  620. * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
  621. * a slash too, so an additional check about presence of leading system server base is implemented. For example, the function is
  622. * able to distinguish type difference between /var/www/chamilo/courses/ (SYS) and /chamilo/courses/ (REL).
  623. * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
  624. * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
  625. * It has not been identified as needed yet.
  626. * 4. Also, resolving the meta-symbols "." and ".." within paths has not been implemented, it is to be identified as needed.
  627. *
  628. * For examples go to: *
  629. * See main/admin/system_status.php?section=paths
  630. *
  631. * Vchamilo changes : allow using an alternate configuration
  632. * to get vchamilo instance paths
  633. */
  634. function api_get_path($path = '', $configuration = [])
  635. {
  636. global $paths;
  637. // get proper configuration data if exists
  638. global $_configuration;
  639. $emptyConfigurationParam = false;
  640. if (empty($configuration)) {
  641. $configuration = (array) $_configuration;
  642. $emptyConfigurationParam = true;
  643. }
  644. $course_folder = 'courses/';
  645. $code_folder = 'main/';
  646. $root_sys = Container::getRootDir();
  647. $root_web = '';
  648. // If no $root_web has been set so far *and* no custom config has been passed to the function
  649. // then re-use the previously-calculated (run-specific) $root_web and skip this complex calculation
  650. if (empty($root_web) || $emptyConfigurationParam === false || empty($configuration)) {
  651. // Resolve master hostname.
  652. if (!empty($configuration) && array_key_exists('root_web', $configuration)) {
  653. $root_web = $configuration['root_web'];
  654. } else {
  655. $root_web = '';
  656. // Try guess it from server.
  657. if (defined('SYSTEM_INSTALLATION') && SYSTEM_INSTALLATION) {
  658. if (($pos = strpos(($requested_page_rel = api_get_self()), 'main/install')) !== false) {
  659. $root_rel = substr($requested_page_rel, 0, $pos);
  660. // See http://www.mediawiki.org/wiki/Manual:$wgServer
  661. $server_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
  662. $server_name =
  663. isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME']
  664. : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
  665. : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
  666. : (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR']
  667. : 'localhost')));
  668. if (isset($_SERVER['SERVER_PORT']) && !strpos($server_name, ':')
  669. && (($server_protocol == 'http'
  670. && $_SERVER['SERVER_PORT'] != 80) || ($server_protocol == 'https' && $_SERVER['SERVER_PORT'] != 443))
  671. ) {
  672. $server_name .= ":".$_SERVER['SERVER_PORT'];
  673. }
  674. $root_web = $server_protocol.'://'.$server_name.$root_rel;
  675. $root_sys = str_replace('\\', '/', realpath(__DIR__.'/../../../')).'/';
  676. }
  677. // Here we give up, so we don't touch anything.
  678. }
  679. }
  680. }
  681. if (isset(Container::$container)) {
  682. $root_web = Container::$container->get('router')->generate(
  683. 'legacy_index',
  684. [],
  685. UrlGeneratorInterface::ABSOLUTE_URL
  686. );
  687. // Fix for php files inside main
  688. if (strpos($root_web, 'main') !== false) {
  689. $pos = (int) strpos($root_web, 'main');
  690. $root_web = substr($root_web, 0, $pos);
  691. }
  692. // Fix for php files inside courses
  693. if (strpos($root_web, '/courses/') !== false) {
  694. $pos = (int) strpos($root_web, '/courses/');
  695. $root_web = substr($root_web, 0, $pos);
  696. }
  697. $root_web = urldecode($root_web);
  698. }
  699. $root_web = str_replace('public/../', '', $root_web);
  700. if (isset($configuration['multiple_access_urls']) &&
  701. $configuration['multiple_access_urls']
  702. ) {
  703. // To avoid that the api_get_access_url() function fails since global.inc.php also calls the main_api.lib.php
  704. if (isset($configuration['access_url']) && !empty($configuration['access_url'])) {
  705. // We look into the DB the function api_get_access_url
  706. $urlInfo = api_get_access_url($configuration['access_url']);
  707. // Avoid default value
  708. $defaultValues = ['http://localhost/', 'https://localhost/'];
  709. if (!empty($urlInfo['url']) && !in_array($urlInfo['url'], $defaultValues)) {
  710. $root_web = $urlInfo['active'] == 1 ? $urlInfo['url'] : $configuration['root_web'];
  711. }
  712. }
  713. }
  714. $paths = [];
  715. // Initialise cache with default values.
  716. if (!array_key_exists($root_web, $paths)) {
  717. $paths[$root_web] = [
  718. WEB_PATH => '',
  719. SYS_PATH => '',
  720. REL_PATH => '',
  721. WEB_COURSE_PATH => '',
  722. SYS_COURSE_PATH => '',
  723. REL_COURSE_PATH => '',
  724. WEB_CODE_PATH => 'main/',
  725. SYS_CODE_PATH => 'main/',
  726. REL_CODE_PATH => '/main/',
  727. SYS_LANG_PATH => 'lang/',
  728. WEB_IMG_PATH => 'public/img/',
  729. WEB_CSS_PATH => 'public/build/css/',
  730. SYS_CSS_PATH => 'public/build/css/',
  731. SYS_PLUGIN_PATH => 'plugin/',
  732. WEB_PLUGIN_PATH => 'plugin/',
  733. WEB_PLUGIN_ASSET_PATH => 'public/plugins/',
  734. SYS_ARCHIVE_PATH => 'var/cache/',
  735. WEB_ARCHIVE_PATH => 'var/cache/',
  736. SYS_HOME_PATH => 'app/home/',
  737. WEB_HOME_PATH => 'app/home/',
  738. REL_HOME_PATH => 'app/home/',
  739. SYS_APP_PATH => 'var/',
  740. SYS_UPLOAD_PATH => 'var/upload/',
  741. SYS_INC_PATH => 'inc/',
  742. CONFIGURATION_PATH => 'app/config/',
  743. LIBRARY_PATH => 'inc/lib/',
  744. WEB_LIBRARY_PATH => 'inc/lib/',
  745. WEB_LIBRARY_JS_PATH => 'inc/lib/javascript/',
  746. WEB_AJAX_PATH => 'inc/ajax/',
  747. SYS_TEST_PATH => 'tests/',
  748. WEB_TEMPLATE_PATH => 'template/',
  749. SYS_TEMPLATE_PATH => 'template/',
  750. WEB_UPLOAD_PATH => 'var/upload/',
  751. WEB_PUBLIC_PATH => 'public/',
  752. SYS_PUBLIC_PATH => 'public/',
  753. WEB_FONTS_PATH => 'fonts/',
  754. SYS_FONTS_PATH => 'fonts/',
  755. ];
  756. }
  757. $isInitialized = [];
  758. $root_rel = $_SERVER['APP_URL_APPEND'] ?? '';
  759. if (!empty($root_rel)) {
  760. // Adds "/" to the root_rel
  761. $hasSlash = substr($root_rel, 0, 1);
  762. if ($hasSlash !== '/') {
  763. $root_rel = '/'.$root_rel;
  764. }
  765. }
  766. // Web server base and system server base.
  767. if (!array_key_exists($root_web, $isInitialized)) {
  768. // Dealing with trailing slashes.
  769. $rootWebWithSlash = api_add_trailing_slash($root_web);
  770. $root_sys = api_add_trailing_slash($root_sys);
  771. $root_rel = api_add_trailing_slash($root_rel);
  772. // Initialization of a table that contains common-purpose paths.
  773. $paths[$root_web][REL_PATH] = $root_rel;
  774. $paths[$root_web][REL_COURSE_PATH] = $root_rel.$course_folder;
  775. $paths[$root_web][REL_CODE_PATH] = $root_rel.$code_folder;
  776. $paths[$root_web][WEB_PATH] = $rootWebWithSlash;
  777. $paths[$root_web][WEB_CODE_PATH] = $rootWebWithSlash.$code_folder;
  778. $paths[$root_web][WEB_COURSE_PATH] = $rootWebWithSlash.$course_folder;
  779. $paths[$root_web][WEB_PLUGIN_PATH] = $rootWebWithSlash.$paths[$root_web][WEB_PLUGIN_PATH];
  780. $paths[$root_web][WEB_PLUGIN_ASSET_PATH] = $rootWebWithSlash.$paths[$root_web][WEB_PLUGIN_ASSET_PATH];
  781. $paths[$root_web][WEB_ARCHIVE_PATH] = $rootWebWithSlash.$paths[$root_web][WEB_ARCHIVE_PATH];
  782. $paths[$root_web][WEB_CSS_PATH] = $rootWebWithSlash.$paths[$root_web][WEB_CSS_PATH];
  783. $paths[$root_web][WEB_UPLOAD_PATH] = $rootWebWithSlash.$paths[$root_web][WEB_UPLOAD_PATH];
  784. $paths[$root_web][WEB_PUBLIC_PATH] = $rootWebWithSlash.$paths[$root_web][WEB_PUBLIC_PATH];
  785. $paths[$root_web][WEB_HOME_PATH] = $rootWebWithSlash.$paths[$root_web][REL_HOME_PATH];
  786. $paths[$root_web][WEB_IMG_PATH] = $rootWebWithSlash.$paths[$root_web][WEB_IMG_PATH];
  787. $paths[$root_web][WEB_LIBRARY_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_PATH];
  788. $paths[$root_web][WEB_LIBRARY_JS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_LIBRARY_JS_PATH];
  789. $paths[$root_web][WEB_AJAX_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_AJAX_PATH];
  790. $paths[$root_web][WEB_FONTS_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_FONTS_PATH];
  791. $paths[$root_web][WEB_TEMPLATE_PATH] = $paths[$root_web][WEB_CODE_PATH].$paths[$root_web][WEB_TEMPLATE_PATH];
  792. $paths[$root_web][SYS_PATH] = $root_sys;
  793. $paths[$root_web][SYS_CODE_PATH] = $root_sys.$code_folder;
  794. $paths[$root_web][SYS_TEST_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_TEST_PATH];
  795. $paths[$root_web][SYS_TEMPLATE_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_TEMPLATE_PATH];
  796. $paths[$root_web][SYS_PUBLIC_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PUBLIC_PATH];
  797. $paths[$root_web][SYS_CSS_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_CSS_PATH];
  798. $paths[$root_web][SYS_FONTS_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_FONTS_PATH];
  799. $paths[$root_web][SYS_ARCHIVE_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_ARCHIVE_PATH];
  800. $paths[$root_web][SYS_APP_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_APP_PATH];
  801. $paths[$root_web][SYS_COURSE_PATH] = $paths[$root_web][SYS_APP_PATH].$course_folder;
  802. $paths[$root_web][SYS_UPLOAD_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_UPLOAD_PATH];
  803. $paths[$root_web][SYS_LANG_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_LANG_PATH];
  804. $paths[$root_web][SYS_HOME_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_HOME_PATH];
  805. $paths[$root_web][SYS_PLUGIN_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][SYS_PLUGIN_PATH];
  806. $paths[$root_web][SYS_INC_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][SYS_INC_PATH];
  807. $paths[$root_web][LIBRARY_PATH] = $paths[$root_web][SYS_CODE_PATH].$paths[$root_web][LIBRARY_PATH];
  808. $paths[$root_web][CONFIGURATION_PATH] = $paths[$root_web][SYS_PATH].$paths[$root_web][CONFIGURATION_PATH];
  809. global $virtualChamilo;
  810. if (!empty($virtualChamilo)) {
  811. $paths[$root_web][SYS_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_ARCHIVE_PATH]);
  812. $paths[$root_web][SYS_HOME_PATH] = api_add_trailing_slash($virtualChamilo[SYS_HOME_PATH]);
  813. $paths[$root_web][SYS_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_COURSE_PATH]);
  814. $paths[$root_web][SYS_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[SYS_UPLOAD_PATH]);
  815. $paths[$root_web][WEB_HOME_PATH] = api_add_trailing_slash($virtualChamilo[WEB_HOME_PATH]);
  816. $paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
  817. $paths[$root_web][WEB_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_ARCHIVE_PATH]);
  818. //$paths[$root_web][WEB_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_COURSE_PATH]);
  819. // WEB_UPLOAD_PATH should be handle by apache htaccess in the vhost
  820. // RewriteEngine On
  821. // RewriteRule /app/upload/(.*)$ http://localhost/other/upload/my-chamilo111-net/$1 [QSA,L]
  822. //$paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
  823. //$paths[$root_web][REL_PATH] = $virtualChamilo[REL_PATH];
  824. //$paths[$root_web][REL_COURSE_PATH] = $virtualChamilo[REL_COURSE_PATH];
  825. }
  826. $isInitialized[$root_web] = true;
  827. }
  828. $path = trim($path);
  829. // Retrieving a common-purpose path.
  830. if (isset($paths[$root_web][$path])) {
  831. return $paths[$root_web][$path];
  832. }
  833. // Second purification.
  834. // Replacing Windows back slashes.
  835. $path = str_replace('\\', '/', $path);
  836. // Query strings sometimes mighth wrongly appear in non-URLs.
  837. // Let us check remove them from all types of paths.
  838. if (($pos = strpos($path, '?')) !== false) {
  839. $path = substr($path, 0, $pos);
  840. }
  841. // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
  842. $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
  843. return $path;
  844. }
  845. /**
  846. * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
  847. *
  848. * @param string $path the input path
  849. *
  850. * @return string returns the modified path
  851. */
  852. function api_add_trailing_slash($path)
  853. {
  854. return substr($path, -1) == '/' ? $path : $path.'/';
  855. }
  856. /**
  857. * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
  858. *
  859. * @param string $path the input path
  860. *
  861. * @return string returns the modified path
  862. */
  863. function api_remove_trailing_slash($path)
  864. {
  865. return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
  866. }
  867. /**
  868. * Checks the RFC 3986 syntax of a given URL.
  869. *
  870. * @param string $url the URL to be checked
  871. * @param bool $absolute whether the URL is absolute (beginning with a scheme such as "http:")
  872. *
  873. * @return string|false Returns the URL if it is valid, FALSE otherwise.
  874. * This function is an adaptation from the function valid_url(), Drupal CMS.
  875. *
  876. * @see http://drupal.org
  877. * Note: The built-in function filter_var($urs, FILTER_VALIDATE_URL) has a bug for some versions of PHP.
  878. * @see http://bugs.php.net/51192
  879. */
  880. function api_valid_url($url, $absolute = false)
  881. {
  882. if ($absolute) {
  883. if (preg_match("
  884. /^ # Start at the beginning of the text
  885. (?:ftp|https?|feed):\/\/ # Look for ftp, http, https or feed schemes
  886. (?: # Userinfo (optional) which is typically
  887. (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)* # a username or a username and password
  888. (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@ # combination
  889. )?
  890. (?:
  891. (?:[a-z0-9\-\.]|%[0-9a-f]{2})+ # A domain name or a IPv4 address
  892. |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\]) # or a well formed IPv6 address
  893. )
  894. (?::[0-9]+)? # Server port number (optional)
  895. (?:[\/|\?]
  896. (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2}) # The path and query (optional)
  897. *)?
  898. $/xi", $url)) {
  899. return $url;
  900. }
  901. return false;
  902. } else {
  903. return preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url) ? $url : false;
  904. }
  905. }
  906. /**
  907. * Checks whether a given string looks roughly like an email address.
  908. *
  909. * @param string $address the e-mail address to be checked
  910. *
  911. * @return mixed returns the e-mail if it is valid, FALSE otherwise
  912. */
  913. function api_valid_email($address)
  914. {
  915. return filter_var($address, FILTER_VALIDATE_EMAIL);
  916. }
  917. /* PROTECTION FUNCTIONS
  918. Use these functions to protect your scripts. */
  919. /**
  920. * Function used to protect a course script.
  921. * The function blocks access when
  922. * - there is no $_SESSION["_course"] defined; or
  923. * - $is_allowed_in_course is set to false (this depends on the course
  924. * visibility and user status).
  925. *
  926. * This is only the first proposal, test and improve!
  927. *
  928. * @param bool Option to print headers when displaying error message. Default: false
  929. * @param bool whether session admins should be allowed or not
  930. * @param bool $checkTool check if tool is available for users (user, group)
  931. *
  932. * @return bool True if the user has access to the current course or is out of a course context, false otherwise
  933. *
  934. * @todo replace global variable
  935. *
  936. * @author Roan Embrechts
  937. */
  938. function api_protect_course_script($print_headers = false, $allow_session_admins = false, $checkTool = '')
  939. {
  940. $course_info = api_get_course_info();
  941. if (empty($course_info)) {
  942. api_not_allowed($print_headers);
  943. return false;
  944. }
  945. if (api_is_drh()) {
  946. return true;
  947. }
  948. // Session admin has access to course
  949. $sessionAccess = api_get_configuration_value('session_admins_access_all_content');
  950. if ($sessionAccess) {
  951. $allow_session_admins = true;
  952. }
  953. if (api_is_platform_admin($allow_session_admins)) {
  954. return true;
  955. }
  956. $isAllowedInCourse = api_is_allowed_in_course();
  957. $is_visible = false;
  958. if (isset($course_info) && isset($course_info['visibility'])) {
  959. switch ($course_info['visibility']) {
  960. default:
  961. case COURSE_VISIBILITY_CLOSED:
  962. // Completely closed: the course is only accessible to the teachers. - 0
  963. if (api_get_user_id() && !api_is_anonymous() && $isAllowedInCourse) {
  964. $is_visible = true;
  965. }
  966. break;
  967. case COURSE_VISIBILITY_REGISTERED:
  968. // Private - access authorized to course members only - 1
  969. if (api_get_user_id() && !api_is_anonymous() && $isAllowedInCourse) {
  970. $is_visible = true;
  971. }
  972. break;
  973. case COURSE_VISIBILITY_OPEN_PLATFORM:
  974. // Open - access allowed for users registered on the platform - 2
  975. if (api_get_user_id() && !api_is_anonymous() && $isAllowedInCourse) {
  976. $is_visible = true;
  977. }
  978. break;
  979. case COURSE_VISIBILITY_OPEN_WORLD:
  980. //Open - access allowed for the whole world - 3
  981. $is_visible = true;
  982. break;
  983. case COURSE_VISIBILITY_HIDDEN:
  984. //Completely closed: the course is only accessible to the teachers. - 0
  985. if (api_is_platform_admin()) {
  986. $is_visible = true;
  987. }
  988. break;
  989. }
  990. //If password is set and user is not registered to the course then the course is not visible
  991. if ($isAllowedInCourse == false &&
  992. isset($course_info['registration_code']) &&
  993. !empty($course_info['registration_code'])
  994. ) {
  995. $is_visible = false;
  996. }
  997. }
  998. if (!empty($checkTool)) {
  999. if (!api_is_allowed_to_edit(true, true, true)) {
  1000. $toolInfo = api_get_tool_information_by_name($checkTool);
  1001. if (!empty($toolInfo) && isset($toolInfo['visibility']) && $toolInfo['visibility'] == 0) {
  1002. api_not_allowed(true);
  1003. return false;
  1004. }
  1005. }
  1006. }
  1007. // Check session visibility
  1008. $session_id = api_get_session_id();
  1009. if (!empty($session_id)) {
  1010. // $isAllowedInCourse was set in local.inc.php
  1011. if (!$isAllowedInCourse) {
  1012. $is_visible = false;
  1013. }
  1014. }
  1015. if (!$is_visible) {
  1016. api_not_allowed($print_headers);
  1017. return false;
  1018. }
  1019. return true;
  1020. }
  1021. /**
  1022. * Function used to protect an admin script.
  1023. *
  1024. * The function blocks access when the user has no platform admin rights
  1025. * with an error message printed on default output
  1026. *
  1027. * @param bool Whether to allow session admins as well
  1028. * @param bool Whether to allow HR directors as well
  1029. * @param string An optional message (already passed through get_lang)
  1030. *
  1031. * @return bool True if user is allowed, false otherwise.
  1032. * The function also outputs an error message in case not allowed
  1033. *
  1034. * @author Roan Embrechts (original author)
  1035. */
  1036. function api_protect_admin_script($allow_sessions_admins = false, $allow_drh = false, $message = null)
  1037. {
  1038. if (!api_is_platform_admin($allow_sessions_admins, $allow_drh)) {
  1039. api_not_allowed(true, $message);
  1040. return false;
  1041. }
  1042. return true;
  1043. }
  1044. /**
  1045. * Function used to protect a teacher script.
  1046. * The function blocks access when the user has no teacher rights.
  1047. *
  1048. * @return bool True if the current user can access the script, false otherwise
  1049. *
  1050. * @author Yoselyn Castillo
  1051. */
  1052. function api_protect_teacher_script()
  1053. {
  1054. if (!api_is_allowed_to_edit()) {
  1055. api_not_allowed(true);
  1056. return false;
  1057. }
  1058. return true;
  1059. }
  1060. /**
  1061. * Function used to prevent anonymous users from accessing a script.
  1062. *
  1063. * @param bool|true $printHeaders
  1064. *
  1065. * @author Roan Embrechts
  1066. *
  1067. * @return bool
  1068. */
  1069. function api_block_anonymous_users($printHeaders = true)
  1070. {
  1071. $user = api_get_user_info();
  1072. if (!(isset($user['user_id']) && $user['user_id']) || api_is_anonymous($user['user_id'], true)) {
  1073. api_not_allowed($printHeaders);
  1074. return false;
  1075. }
  1076. return true;
  1077. }
  1078. /**
  1079. * Returns a rough evaluation of the browser's name and version based on very
  1080. * simple regexp.
  1081. *
  1082. * @return array with the navigator name and version ['name' => '...', 'version' => '...']
  1083. */
  1084. function api_get_navigator()
  1085. {
  1086. $navigator = 'Unknown';
  1087. $version = 0;
  1088. if (!isset($_SERVER['HTTP_USER_AGENT'])) {
  1089. return ['name' => 'Unknown', 'version' => '0.0.0'];
  1090. }
  1091. if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
  1092. $navigator = 'Opera';
  1093. list(, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
  1094. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Edge') !== false) {
  1095. $navigator = 'Edge';
  1096. list(, $version) = explode('Edge', $_SERVER['HTTP_USER_AGENT']);
  1097. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
  1098. $navigator = 'Internet Explorer';
  1099. list(, $version) = explode('MSIE ', $_SERVER['HTTP_USER_AGENT']);
  1100. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
  1101. $navigator = 'Chrome';
  1102. list(, $version) = explode('Chrome', $_SERVER['HTTP_USER_AGENT']);
  1103. } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'Safari') !== false) {
  1104. $navigator = 'Safari';
  1105. if (stripos($_SERVER['HTTP_USER_AGENT'], 'Version/') !== false) {
  1106. // If this Safari does have the "Version/" string in its user agent
  1107. // then use that as a version indicator rather than what's after
  1108. // "Safari/" which is rather a "build number" or something
  1109. list(, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
  1110. } else {
  1111. list(, $version) = explode('Safari/', $_SERVER['HTTP_USER_AGENT']);
  1112. }
  1113. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox') !== false) {
  1114. $navigator = 'Firefox';
  1115. list(, $version) = explode('Firefox', $_SERVER['HTTP_USER_AGENT']);
  1116. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
  1117. $navigator = 'Netscape';
  1118. if (stripos($_SERVER['HTTP_USER_AGENT'], 'Netscape/') !== false) {
  1119. list(, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
  1120. } else {
  1121. list(, $version) = explode('Navigator', $_SERVER['HTTP_USER_AGENT']);
  1122. }
  1123. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
  1124. $navigator = 'Konqueror';
  1125. list(, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
  1126. } elseif (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
  1127. $navigator = 'AppleWebKit';
  1128. list(, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
  1129. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
  1130. $navigator = 'Mozilla';
  1131. list(, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
  1132. }
  1133. // Now cut extra stuff around (mostly *after*) the version number
  1134. $version = preg_replace('/^([\/\s])?([\d\.]+)?.*/', '\2', $version);
  1135. if (strpos($version, '.') === false) {
  1136. $version = number_format(doubleval($version), 1);
  1137. }
  1138. $return = ['name' => $navigator, 'version' => $version];
  1139. return $return;
  1140. }
  1141. /**
  1142. * @return true if user self registration is allowed, false otherwise
  1143. */
  1144. function api_is_self_registration_allowed()
  1145. {
  1146. return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
  1147. }
  1148. /**
  1149. * This function returns the id of the user which is stored in the $_user array.
  1150. *
  1151. * example: The function can be used to check if a user is logged in
  1152. * if (api_get_user_id())
  1153. *
  1154. * @return int the id of the current user, 0 if is empty
  1155. */
  1156. function api_get_user_id()
  1157. {
  1158. $userInfo = Session::read('_user');
  1159. if ($userInfo && isset($userInfo['user_id'])) {
  1160. return (int) $userInfo['user_id'];
  1161. }
  1162. return 0;
  1163. }
  1164. /**
  1165. * Gets the list of courses a specific user is subscribed to.
  1166. *
  1167. * @param int User ID
  1168. * @param bool $fetch_session Whether to get session courses or not - NOT YET IMPLEMENTED
  1169. *
  1170. * @return array Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
  1171. *
  1172. * @deprecated use CourseManager::get_courses_list_by_user_id()
  1173. */
  1174. function api_get_user_courses($userId, $fetch_session = true)
  1175. {
  1176. // Get out if not integer
  1177. if ($userId != strval(intval($userId))) {
  1178. return [];
  1179. }
  1180. $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
  1181. $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  1182. $sql = "SELECT cc.id as real_id, cc.code code, cc.directory dir, cu.status status
  1183. FROM $t_course cc, $t_course_user cu
  1184. WHERE
  1185. cc.id = cu.c_id AND
  1186. cu.user_id = $userId AND
  1187. cu.relation_type <> ".COURSE_RELATION_TYPE_RRHH;
  1188. $result = Database::query($sql);
  1189. if ($result === false) {
  1190. return [];
  1191. }
  1192. $courses = [];
  1193. while ($row = Database::fetch_array($result)) {
  1194. // we only need the database name of the course
  1195. $courses[] = $row;
  1196. }
  1197. return $courses;
  1198. }
  1199. /**
  1200. * Formats user information into a standard array
  1201. * This function should be only used inside api_get_user_info().
  1202. *
  1203. * @param array Non-standard user array
  1204. * @param bool $add_password
  1205. * @param bool $loadAvatars turn off to improve performance
  1206. *
  1207. * @return array Standard user array
  1208. */
  1209. function _api_format_user($user, $add_password = false, $loadAvatars = true)
  1210. {
  1211. $result = [];
  1212. if (!isset($user['user_id'])) {
  1213. return [];
  1214. }
  1215. $result['firstname'] = null;
  1216. $result['lastname'] = null;
  1217. if (isset($user['firstname']) && isset($user['lastname'])) {
  1218. // with only lowercase
  1219. $result['firstname'] = $user['firstname'];
  1220. $result['lastname'] = $user['lastname'];
  1221. } elseif (isset($user['firstName']) && isset($user['lastName'])) {
  1222. // with uppercase letters
  1223. $result['firstname'] = isset($user['firstName']) ? $user['firstName'] : null;
  1224. $result['lastname'] = isset($user['lastName']) ? $user['lastName'] : null;
  1225. }
  1226. if (isset($user['email'])) {
  1227. $result['mail'] = isset($user['email']) ? $user['email'] : null;
  1228. $result['email'] = isset($user['email']) ? $user['email'] : null;
  1229. } else {
  1230. $result['mail'] = isset($user['mail']) ? $user['mail'] : null;
  1231. $result['email'] = isset($user['mail']) ? $user['mail'] : null;
  1232. }
  1233. $result['complete_name'] = api_get_person_name($result['firstname'], $result['lastname']);
  1234. $result['complete_name_with_username'] = $result['complete_name'];
  1235. if (!empty($user['username']) && api_get_setting('profile.hide_username_with_complete_name') === 'false') {
  1236. $result['complete_name_with_username'] = $result['complete_name'].' ('.$user['username'].')';
  1237. }
  1238. $showEmail = api_get_setting('show_email_addresses') === 'true';
  1239. if (!empty($user['email'])) {
  1240. $result['complete_name_with_email_forced'] = $result['complete_name'].' ('.$user['email'].')';
  1241. if ($showEmail) {
  1242. $result['complete_name_with_email'] = $result['complete_name'].' ('.$user['email'].')';
  1243. }
  1244. } else {
  1245. $result['complete_name_with_email'] = $result['complete_name'];
  1246. $result['complete_name_with_email_forced'] = $result['complete_name'];
  1247. }
  1248. // Kept for historical reasons
  1249. $result['firstName'] = $result['firstname'];
  1250. $result['lastName'] = $result['lastname'];
  1251. $attributes = [
  1252. 'phone',
  1253. 'address',
  1254. 'picture_uri',
  1255. 'official_code',
  1256. 'status',
  1257. 'active',
  1258. 'auth_source',
  1259. 'username',
  1260. 'theme',
  1261. 'language',
  1262. 'creator_id',
  1263. 'registration_date',
  1264. 'hr_dept_id',
  1265. 'expiration_date',
  1266. 'last_login',
  1267. 'user_is_online',
  1268. ];
  1269. if (api_get_setting('extended_profile') === 'true') {
  1270. $attributes[] = 'competences';
  1271. $attributes[] = 'diplomas';
  1272. $attributes[] = 'teach';
  1273. $attributes[] = 'openarea';
  1274. }
  1275. foreach ($attributes as $attribute) {
  1276. $result[$attribute] = isset($user[$attribute]) ? $user[$attribute] : null;
  1277. }
  1278. $user_id = (int) $user['user_id'];
  1279. // Maintain the user_id index for backwards compatibility
  1280. $result['user_id'] = $result['id'] = $user_id;
  1281. $hasCertificates = Certificate::getCertificateByUser($user_id);
  1282. $result['has_certificates'] = 0;
  1283. if (!empty($hasCertificates)) {
  1284. $result['has_certificates'] = 1;
  1285. }
  1286. $result['icon_status'] = '';
  1287. $result['icon_status_medium'] = '';
  1288. $result['is_admin'] = UserManager::is_admin($user_id);
  1289. // Getting user avatar.
  1290. if ($loadAvatars) {
  1291. $result['avatar'] = '';
  1292. $result['avatar_no_query'] = '';
  1293. $result['avatar_small'] = '';
  1294. $result['avatar_medium'] = '';
  1295. if (!isset($user['avatar'])) {
  1296. $originalFile = UserManager::getUserPicture(
  1297. $user_id,
  1298. USER_IMAGE_SIZE_ORIGINAL,
  1299. null,
  1300. $result
  1301. );
  1302. $result['avatar'] = $originalFile;
  1303. $avatarString = explode('?', $result['avatar']);
  1304. $result['avatar_no_query'] = reset($avatarString);
  1305. } else {
  1306. $result['avatar'] = $user['avatar'];
  1307. $avatarString = explode('?', $user['avatar']);
  1308. $result['avatar_no_query'] = reset($avatarString);
  1309. }
  1310. if (!isset($user['avatar_small'])) {
  1311. $smallFile = UserManager::getUserPicture(
  1312. $user_id,
  1313. USER_IMAGE_SIZE_SMALL,
  1314. null,
  1315. $result
  1316. );
  1317. $result['avatar_small'] = $smallFile;
  1318. } else {
  1319. $result['avatar_small'] = $user['avatar_small'];
  1320. }
  1321. if (!isset($user['avatar_medium'])) {
  1322. $mediumFile = UserManager::getUserPicture(
  1323. $user_id,
  1324. USER_IMAGE_SIZE_MEDIUM,
  1325. null,
  1326. $result
  1327. );
  1328. $result['avatar_medium'] = $mediumFile;
  1329. } else {
  1330. $result['avatar_medium'] = $user['avatar_medium'];
  1331. }
  1332. $urlImg = api_get_path(WEB_IMG_PATH);
  1333. $iconStatus = '';
  1334. $iconStatusMedium = '';
  1335. switch ($result['status']) {
  1336. case STUDENT:
  1337. if ($result['has_certificates']) {
  1338. $iconStatus = $urlImg.'icons/svg/identifier_graduated.svg';
  1339. } else {
  1340. $iconStatus = $urlImg.'icons/svg/identifier_student.svg';
  1341. }
  1342. break;
  1343. case COURSEMANAGER:
  1344. if ($result['is_admin']) {
  1345. $iconStatus = $urlImg.'icons/svg/identifier_admin.svg';
  1346. } else {
  1347. $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
  1348. }
  1349. break;
  1350. case STUDENT_BOSS:
  1351. $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
  1352. break;
  1353. }
  1354. if (!empty($iconStatus)) {
  1355. $iconStatusMedium = '<img src="'.$iconStatus.'" width="32px" height="32px">';
  1356. $iconStatus = '<img src="'.$iconStatus.'" width="22px" height="22px">';
  1357. }
  1358. $result['icon_status'] = $iconStatus;
  1359. $result['icon_status_medium'] = $iconStatusMedium;
  1360. }
  1361. if (isset($user['user_is_online'])) {
  1362. $result['user_is_online'] = $user['user_is_online'] == true ? 1 : 0;
  1363. }
  1364. if (isset($user['user_is_online_in_chat'])) {
  1365. $result['user_is_online_in_chat'] = (int) $user['user_is_online_in_chat'];
  1366. }
  1367. if ($add_password) {
  1368. $result['password'] = $user['password'];
  1369. }
  1370. if (isset($result['profile_completed'])) {
  1371. $result['profile_completed'] = $user['profile_completed'];
  1372. }
  1373. $result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
  1374. // Send message link
  1375. $sendMessage = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$user_id;
  1376. $result['complete_name_with_message_link'] = Display::url(
  1377. $result['complete_name_with_username'],
  1378. $sendMessage,
  1379. ['class' => 'ajax']
  1380. );
  1381. if (isset($user['extra'])) {
  1382. $result['extra'] = $user['extra'];
  1383. }
  1384. return $result;
  1385. }
  1386. /**
  1387. * Finds all the information about a user.
  1388. * If no parameter is passed you find all the information about the current user.
  1389. *
  1390. * @param int $user_id
  1391. * @param bool $checkIfUserOnline
  1392. * @param bool $showPassword
  1393. * @param bool $loadExtraData
  1394. * @param bool $loadOnlyVisibleExtraData Get the user extra fields that are visible
  1395. * @param bool $loadAvatars turn off to improve performance and if avatars are not needed
  1396. * @param bool $updateCache update apc cache if exists
  1397. *
  1398. * @return mixed $user_info user_id, lastname, firstname, username, email, etc or false on error
  1399. *
  1400. * @author Patrick Cool <patrick.cool@UGent.be>
  1401. * @author Julio Montoya
  1402. *
  1403. * @version 21 September 2004
  1404. */
  1405. function api_get_user_info(
  1406. $user_id = 0,
  1407. $checkIfUserOnline = false,
  1408. $showPassword = false,
  1409. $loadExtraData = false,
  1410. $loadOnlyVisibleExtraData = false,
  1411. $loadAvatars = true,
  1412. $updateCache = false
  1413. ) {
  1414. $apcVar = null;
  1415. $user = false;
  1416. $cacheAvailable = api_get_configuration_value('apc');
  1417. if (empty($user_id)) {
  1418. $userFromSession = Session::read('_user');
  1419. if (isset($userFromSession)) {
  1420. if ($cacheAvailable === true &&
  1421. (
  1422. empty($userFromSession['is_anonymous']) &&
  1423. (isset($userFromSession['status']) && $userFromSession['status'] != ANONYMOUS)
  1424. )
  1425. ) {
  1426. $apcVar = api_get_configuration_value('apc_prefix').'userinfo_'.$userFromSession['user_id'];
  1427. if (apcu_exists($apcVar)) {
  1428. if ($updateCache) {
  1429. apcu_store($apcVar, $userFromSession, 60);
  1430. }
  1431. $user = apcu_fetch($apcVar);
  1432. } else {
  1433. $user = _api_format_user(
  1434. $userFromSession,
  1435. $showPassword,
  1436. $loadAvatars
  1437. );
  1438. apcu_store($apcVar, $user, 60);
  1439. }
  1440. } else {
  1441. $user = _api_format_user(
  1442. $userFromSession,
  1443. $showPassword,
  1444. $loadAvatars
  1445. );
  1446. }
  1447. return $user;
  1448. }
  1449. return false;
  1450. }
  1451. // Make sure user_id is safe
  1452. $user_id = (int) $user_id;
  1453. // Re-use user information if not stale and already stored in APCu
  1454. if ($cacheAvailable === true) {
  1455. $apcVar = api_get_configuration_value('apc_prefix').'userinfo_'.$user_id;
  1456. if (apcu_exists($apcVar) && $updateCache == false && $checkIfUserOnline == false) {
  1457. $user = apcu_fetch($apcVar);
  1458. return $user;
  1459. }
  1460. }
  1461. $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
  1462. WHERE id = $user_id";
  1463. $result = Database::query($sql);
  1464. if (Database::num_rows($result) > 0) {
  1465. $result_array = Database::fetch_array($result);
  1466. $result_array['user_is_online_in_chat'] = 0;
  1467. if ($checkIfUserOnline) {
  1468. $use_status_in_platform = user_is_online($user_id);
  1469. $result_array['user_is_online'] = $use_status_in_platform;
  1470. $user_online_in_chat = 0;
  1471. if ($use_status_in_platform) {
  1472. $user_status = UserManager::get_extra_user_data_by_field(
  1473. $user_id,
  1474. 'user_chat_status',
  1475. false,
  1476. true
  1477. );
  1478. if ((int) $user_status['user_chat_status'] == 1) {
  1479. $user_online_in_chat = 1;
  1480. }
  1481. }
  1482. $result_array['user_is_online_in_chat'] = $user_online_in_chat;
  1483. }
  1484. if ($loadExtraData) {
  1485. $fieldValue = new ExtraFieldValue('user');
  1486. $result_array['extra'] = $fieldValue->getAllValuesForAnItem(
  1487. $user_id,
  1488. $loadOnlyVisibleExtraData
  1489. );
  1490. }
  1491. $user = _api_format_user($result_array, $showPassword, $loadAvatars);
  1492. }
  1493. if ($cacheAvailable === true) {
  1494. apcu_store($apcVar, $user, 60);
  1495. }
  1496. return $user;
  1497. }
  1498. /**
  1499. * @param int $userId
  1500. *
  1501. * @return User
  1502. */
  1503. function api_get_user_entity($userId)
  1504. {
  1505. $userId = (int) $userId;
  1506. $repo = UserManager::getRepository();
  1507. /** @var User $user */
  1508. $user = $repo->find($userId);
  1509. return $user;
  1510. }
  1511. /**
  1512. * @return User|null
  1513. */
  1514. function api_get_current_user()
  1515. {
  1516. $isLoggedIn = Container::$container->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_REMEMBERED');
  1517. if ($isLoggedIn === false) {
  1518. return null;
  1519. }
  1520. $token = Container::$container->get('security.token_storage')->getToken();
  1521. if (null !== $token) {
  1522. return $token->getUser();
  1523. }
  1524. return null;
  1525. }
  1526. /**
  1527. * Finds all the information about a user from username instead of user id.
  1528. *
  1529. * @param string $username
  1530. *
  1531. * @return mixed $user_info array user_id, lastname, firstname, username, email or false on error
  1532. *
  1533. * @author Yannick Warnier <yannick.warnier@beeznest.com>
  1534. */
  1535. function api_get_user_info_from_username($username = '')
  1536. {
  1537. if (empty($username)) {
  1538. return false;
  1539. }
  1540. $username = trim($username);
  1541. $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
  1542. WHERE username='".Database::escape_string($username)."'";
  1543. $result = Database::query($sql);
  1544. if (Database::num_rows($result) > 0) {
  1545. $resultArray = Database::fetch_array($result);
  1546. return _api_format_user($resultArray);
  1547. }
  1548. return false;
  1549. }
  1550. /**
  1551. * Get first user with an email.
  1552. *
  1553. * @param string $email
  1554. *
  1555. * @return array|bool
  1556. */
  1557. function api_get_user_info_from_email($email = '')
  1558. {
  1559. if (empty($email)) {
  1560. return false;
  1561. }
  1562. $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
  1563. WHERE email ='".Database::escape_string($email)."' LIMIT 1";
  1564. $result = Database::query($sql);
  1565. if (Database::num_rows($result) > 0) {
  1566. $resultArray = Database::fetch_array($result);
  1567. return _api_format_user($resultArray);
  1568. }
  1569. return false;
  1570. }
  1571. /**
  1572. * @return string
  1573. */
  1574. function api_get_course_id()
  1575. {
  1576. return Session::read('_cid', null);
  1577. }
  1578. /**
  1579. * Returns the current course id (integer).
  1580. *
  1581. * @param string $code Optional course code
  1582. *
  1583. * @return int
  1584. */
  1585. function api_get_course_int_id($code = null)
  1586. {
  1587. if (!empty($code)) {
  1588. $code = Database::escape_string($code);
  1589. $row = Database::select(
  1590. 'id',
  1591. Database::get_main_table(TABLE_MAIN_COURSE),
  1592. ['where' => ['code = ?' => [$code]]],
  1593. 'first'
  1594. );
  1595. if (is_array($row) && isset($row['id'])) {
  1596. return $row['id'];
  1597. } else {
  1598. return false;
  1599. }
  1600. }
  1601. return Session::read('_real_cid', 0);
  1602. }
  1603. /**
  1604. * Returns the current course directory.
  1605. *
  1606. * This function relies on api_get_course_info()
  1607. *
  1608. * @param string The course code - optional (takes it from session if not given)
  1609. *
  1610. * @return string The directory where the course is located inside the Chamilo "courses" directory
  1611. *
  1612. * @author Yannick Warnier <yannick.warnier@beeznest.com>
  1613. */
  1614. function api_get_course_path($course_code = null)
  1615. {
  1616. $info = !empty($course_code) ? api_get_course_info($course_code) : api_get_course_info();
  1617. return $info['path'];
  1618. }
  1619. /**
  1620. * Gets a course setting from the current course_setting table. Try always using integer values.
  1621. *
  1622. * @param string $settingName The name of the setting we want from the table
  1623. * @param array $courseInfo
  1624. * @param bool $force force checking the value in the database
  1625. *
  1626. * @return mixed The value of that setting in that table. Return -1 if not found.
  1627. */
  1628. function api_get_course_setting($settingName, $courseInfo = [], $force = false)
  1629. {
  1630. if (empty($courseInfo)) {
  1631. $courseInfo = api_get_course_info();
  1632. }
  1633. if (empty($courseInfo) || empty($settingName)) {
  1634. return -1;
  1635. }
  1636. $courseId = isset($courseInfo['real_id']) && !empty($courseInfo['real_id']) ? $courseInfo['real_id'] : 0;
  1637. if (empty($courseId)) {
  1638. return -1;
  1639. }
  1640. static $courseSettingInfo = [];
  1641. if ($force) {
  1642. $courseSettingInfo = [];
  1643. }
  1644. if (!isset($courseSettingInfo[$courseId])) {
  1645. $table = Database::get_course_table(TABLE_COURSE_SETTING);
  1646. $settingName = Database::escape_string($settingName);
  1647. $sql = "SELECT variable, value FROM $table
  1648. WHERE c_id = $courseId ";
  1649. $res = Database::query($sql);
  1650. if (Database::num_rows($res) > 0) {
  1651. $result = Database::store_result($res, 'ASSOC');
  1652. $courseSettingInfo[$courseId] = array_column($result, 'value', 'variable');
  1653. if (isset($courseSettingInfo[$courseId]['email_alert_manager_on_new_quiz'])) {
  1654. $value = $courseSettingInfo[$courseId]['email_alert_manager_on_new_quiz'];
  1655. if (!is_null($value)) {
  1656. $result = explode(',', $value);
  1657. $courseSettingInfo[$courseId]['email_alert_manager_on_new_quiz'] = $result;
  1658. }
  1659. }
  1660. }
  1661. }
  1662. if (isset($courseSettingInfo[$courseId]) && isset($courseSettingInfo[$courseId][$settingName])) {
  1663. return $courseSettingInfo[$courseId][$settingName];
  1664. }
  1665. return -1;
  1666. }
  1667. /**
  1668. * Gets an anonymous user ID.
  1669. *
  1670. * For some tools that need tracking, like the learnpath tool, it is necessary
  1671. * to have a usable user-id to enable some kind of tracking, even if not
  1672. * perfect. An anonymous ID is taken from the users table by looking for a
  1673. * status of "6" (anonymous).
  1674. *
  1675. * @return int User ID of the anonymous user, or O if no anonymous user found
  1676. */
  1677. function api_get_anonymous_id()
  1678. {
  1679. // Find if another anon is connected now
  1680. $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
  1681. $tableU = Database::get_main_table(TABLE_MAIN_USER);
  1682. $ip = Database::escape_string(api_get_real_ip());
  1683. $max = (int) api_get_configuration_value('max_anonymous_users');
  1684. if ($max >= 2) {
  1685. $sql = "SELECT * FROM $table as TEL
  1686. JOIN $tableU as U
  1687. ON U.user_id = TEL.login_user_id
  1688. WHERE TEL.user_ip = '$ip'
  1689. AND U.status = ".ANONYMOUS."
  1690. AND U.user_id != 2 ";
  1691. $result = Database::query($sql);
  1692. if (empty(Database::num_rows($result))) {
  1693. $login = uniqid('anon_');
  1694. $anonList = UserManager::get_user_list(['status' => ANONYMOUS], ['registration_date ASC']);
  1695. if (count($anonList) >= $max) {
  1696. foreach ($anonList as $userToDelete) {
  1697. UserManager::delete_user($userToDelete['user_id']);
  1698. break;
  1699. }
  1700. }
  1701. $userId = UserManager::create_user(
  1702. $login,
  1703. 'anon',
  1704. ANONYMOUS,
  1705. ' anonymous@localhost',
  1706. $login,
  1707. $login
  1708. );
  1709. return $userId;
  1710. } else {
  1711. $row = Database::fetch_array($result, 'ASSOC');
  1712. return $row['user_id'];
  1713. }
  1714. }
  1715. $table = Database::get_main_table(TABLE_MAIN_USER);
  1716. $sql = "SELECT user_id
  1717. FROM $table
  1718. WHERE status = ".ANONYMOUS." ";
  1719. $res = Database::query($sql);
  1720. if (Database::num_rows($res) > 0) {
  1721. $row = Database::fetch_array($res, 'ASSOC');
  1722. return $row['user_id'];
  1723. }
  1724. // No anonymous user was found.
  1725. return 0;
  1726. }
  1727. /**
  1728. * @param string $courseCode
  1729. * @param int $sessionId
  1730. * @param int $groupId
  1731. *
  1732. * @return string
  1733. */
  1734. function api_get_cidreq_params($courseCode, $sessionId = 0, $groupId = 0)
  1735. {
  1736. $courseCode = !empty($courseCode) ? htmlspecialchars($courseCode) : '';
  1737. $sessionId = !empty($sessionId) ? (int) $sessionId : 0;
  1738. $groupId = !empty($groupId) ? (int) $groupId : 0;
  1739. $url = 'cidReq='.$courseCode;
  1740. $url .= '&id_session='.$sessionId;
  1741. $url .= '&gidReq='.$groupId;
  1742. return $url;
  1743. }
  1744. /**
  1745. * Returns the current course url part including session, group, and gradebook params.
  1746. *
  1747. * @param bool $addSessionId
  1748. * @param bool $addGroupId
  1749. * @param string $origin
  1750. *
  1751. * @return string Course & session references to add to a URL
  1752. */
  1753. function api_get_cidreq($addSessionId = true, $addGroupId = true, $origin = '')
  1754. {
  1755. $courseCode = api_get_course_id();
  1756. $url = empty($courseCode) ? '' : 'cidReq='.htmlspecialchars($courseCode);
  1757. $origin = empty($origin) ? api_get_origin() : Security::remove_XSS($origin);
  1758. if ($addSessionId) {
  1759. if (!empty($url)) {
  1760. $url .= api_get_session_id() == 0 ? '&id_session=0' : '&id_session='.api_get_session_id();
  1761. }
  1762. }
  1763. if ($addGroupId) {
  1764. if (!empty($url)) {
  1765. $url .= api_get_group_id() == 0 ? '&gidReq=0' : '&gidReq='.api_get_group_id();
  1766. }
  1767. }
  1768. if (!empty($url)) {
  1769. $url .= '&gradebook='.(int) api_is_in_gradebook();
  1770. $url .= '&origin='.$origin;
  1771. }
  1772. return $url;
  1773. }
  1774. /**
  1775. * Get if we visited a gradebook page.
  1776. *
  1777. * @return bool
  1778. */
  1779. function api_is_in_gradebook()
  1780. {
  1781. return Session::read('in_gradebook', false);
  1782. }
  1783. /**
  1784. * Set that we are in a page inside a gradebook.
  1785. */
  1786. function api_set_in_gradebook()
  1787. {
  1788. Session::write('in_gradebook', true);
  1789. }
  1790. /**
  1791. * Remove gradebook session.
  1792. */
  1793. function api_remove_in_gradebook()
  1794. {
  1795. Session::erase('in_gradebook');
  1796. }
  1797. /**
  1798. * Returns the current course info array see api_format_course_array()
  1799. * If the course_code is given, the returned array gives info about that
  1800. * particular course, if none given it gets the course info from the session.
  1801. *
  1802. * @param string $course_code
  1803. *
  1804. * @return array
  1805. */
  1806. function api_get_course_info($course_code = null)
  1807. {
  1808. if (!empty($course_code)) {
  1809. $course_code = Database::escape_string($course_code);
  1810. $courseId = api_get_course_int_id($course_code);
  1811. if (empty($courseId)) {
  1812. return [];
  1813. }
  1814. $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
  1815. $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  1816. $sql = "SELECT
  1817. course.*,
  1818. course_category.code faCode,
  1819. course_category.name faName
  1820. FROM $course_table
  1821. LEFT JOIN $course_cat_table
  1822. ON course.category_code = course_category.code
  1823. WHERE course.id = $courseId";
  1824. $result = Database::query($sql);
  1825. $courseInfo = [];
  1826. if (Database::num_rows($result) > 0) {
  1827. $data = Database::fetch_array($result);
  1828. $courseInfo = api_format_course_array($data);
  1829. }
  1830. return $courseInfo;
  1831. }
  1832. $_course = Session::read('_course');
  1833. if ($_course == '-1') {
  1834. $_course = [];
  1835. }
  1836. return $_course;
  1837. }
  1838. /**
  1839. * @param int $courseId
  1840. *
  1841. * @return Course
  1842. */
  1843. function api_get_course_entity($courseId = 0)
  1844. {
  1845. if (empty($courseId)) {
  1846. $courseId = api_get_course_int_id();
  1847. }
  1848. return CourseManager::getManager()->find($courseId);
  1849. }
  1850. /**
  1851. * @param int $id
  1852. *
  1853. * @return SessionEntity
  1854. */
  1855. function api_get_session_entity($id = 0)
  1856. {
  1857. if (empty($id)) {
  1858. $id = api_get_session_id();
  1859. }
  1860. return Database::getManager()->getRepository('ChamiloCoreBundle:Session')->find($id);
  1861. }
  1862. /**
  1863. * @param int $id
  1864. *
  1865. * @return CGroupInfo
  1866. */
  1867. function api_get_group_entity($id = 0)
  1868. {
  1869. if (empty($id)) {
  1870. $id = api_get_group_id();
  1871. }
  1872. return Database::getManager()->getRepository('ChamiloCourseBundle:CGroupInfo')->find($id);
  1873. }
  1874. /**
  1875. * @param int $id
  1876. *
  1877. * @return AccessUrl
  1878. */
  1879. function api_get_url_entity($id = 0)
  1880. {
  1881. if (empty($id)) {
  1882. $id = api_get_current_access_url_id();
  1883. }
  1884. return Container::getAccessUrlRepository()->find($id);
  1885. }
  1886. /**
  1887. * Returns the current course info array.
  1888. * Now if the course_code is given, the returned array gives info about that
  1889. * particular course, not specially the current one.
  1890. *
  1891. * @param int $id Numeric ID of the course
  1892. *
  1893. * @return array The course info as an array formatted by api_format_course_array, including category.name
  1894. */
  1895. function api_get_course_info_by_id($id = 0)
  1896. {
  1897. $id = (int) $id;
  1898. if (empty($id)) {
  1899. $course = Session::read('_course', []);
  1900. return $course;
  1901. }
  1902. $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
  1903. $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  1904. $sql = "SELECT
  1905. course.*,
  1906. course_category.code faCode,
  1907. course_category.name faName,
  1908. course_category.id faId
  1909. FROM $course_table
  1910. LEFT JOIN $course_cat_table
  1911. ON course.category_code = course_category.code
  1912. WHERE course.id = $id";
  1913. $result = Database::query($sql);
  1914. if (Database::num_rows($result) > 0) {
  1915. $row = Database::fetch_array($result);
  1916. $course = api_format_course_array($row);
  1917. return $course;
  1918. }
  1919. return [];
  1920. }
  1921. /**
  1922. * Reformat the course array (output by api_get_course_info()) in order, mostly,
  1923. * to switch from 'code' to 'id' in the array. This is a legacy feature and is
  1924. * now possibly causing massive confusion as a new "id" field has been added to
  1925. * the course table in 1.9.0.
  1926. *
  1927. * @param $course_data
  1928. *
  1929. * @return array
  1930. *
  1931. * @todo eradicate the false "id"=code field of the $_course array and use the int id
  1932. */
  1933. function api_format_course_array($course_data)
  1934. {
  1935. if (empty($course_data)) {
  1936. return [];
  1937. }
  1938. $_course = [];
  1939. $_course['id'] = $course_data['code'];
  1940. $_course['real_id'] = $course_data['id'];
  1941. // Added
  1942. $_course['code'] = $course_data['code'];
  1943. $_course['name'] = $course_data['title'];
  1944. $_course['title'] = $course_data['title'];
  1945. $_course['official_code'] = $course_data['visual_code'];
  1946. $_course['visual_code'] = $course_data['visual_code'];
  1947. $_course['sysCode'] = $course_data['code'];
  1948. $_course['path'] = $course_data['directory']; // Use as key in path.
  1949. $_course['directory'] = $course_data['directory'];
  1950. $_course['creation_date'] = $course_data['creation_date'];
  1951. $_course['titular'] = $course_data['tutor_name'];
  1952. $_course['language'] = $course_data['course_language'];
  1953. $_course['extLink']['url'] = $course_data['department_url'];
  1954. $_course['extLink']['name'] = $course_data['department_name'];
  1955. $_course['categoryCode'] = $course_data['faCode'];
  1956. $_course['categoryName'] = $course_data['faName'];
  1957. $_course['visibility'] = $course_data['visibility'];
  1958. $_course['subscribe_allowed'] = $course_data['subscribe'];
  1959. $_course['subscribe'] = $course_data['subscribe'];
  1960. $_course['unsubscribe'] = $course_data['unsubscribe'];
  1961. $_course['course_language'] = $course_data['course_language'];
  1962. $_course['activate_legal'] = isset($course_data['activate_legal']) ? $course_data['activate_legal'] : false;
  1963. $_course['legal'] = $course_data['legal'];
  1964. $_course['show_score'] = $course_data['show_score']; //used in the work tool
  1965. $_course['department_name'] = $course_data['department_name'];
  1966. $_course['department_url'] = $course_data['department_url'];
  1967. $courseSys = api_get_path(SYS_COURSE_PATH).$course_data['directory'];
  1968. $webCourseHome = api_get_path(WEB_COURSE_PATH).$course_data['directory'];
  1969. // Course password
  1970. $_course['registration_code'] = !empty($course_data['registration_code']) ? sha1($course_data['registration_code']) : null;
  1971. $_course['disk_quota'] = $course_data['disk_quota'];
  1972. $_course['course_public_url'] = $webCourseHome.'/index.php';
  1973. $_course['course_sys_path'] = $courseSys.'/';
  1974. if (array_key_exists('add_teachers_to_sessions_courses', $course_data)) {
  1975. $_course['add_teachers_to_sessions_courses'] = $course_data['add_teachers_to_sessions_courses'];
  1976. }
  1977. // Course image
  1978. $_course['course_image_source'] = '';
  1979. if (file_exists($courseSys.'/course-pic85x85.png')) {
  1980. $url_image = $webCourseHome.'/course-pic85x85.png';
  1981. $_course['course_image_source'] = $courseSys.'/course-pic85x85.png';
  1982. } else {
  1983. $url_image = Display::return_icon(
  1984. 'course.png',
  1985. null,
  1986. null,
  1987. ICON_SIZE_BIG,
  1988. null,
  1989. true,
  1990. false
  1991. );
  1992. }
  1993. $_course['course_image'] = $url_image;
  1994. // Course large image
  1995. $_course['course_image_large_source'] = '';
  1996. if (file_exists($courseSys.'/course-pic.png')) {
  1997. $url_image = $webCourseHome.'/course-pic.png';
  1998. $_course['course_image_large_source'] = $courseSys.'/course-pic.png';
  1999. } else {
  2000. $url_image = Display::return_icon(
  2001. 'session_default.png',
  2002. null,
  2003. null,
  2004. null,
  2005. null,
  2006. true,
  2007. true
  2008. );
  2009. }
  2010. $_course['course_image_large'] = $url_image;
  2011. return $_course;
  2012. }
  2013. /**
  2014. * Returns a difficult to guess password.
  2015. *
  2016. * @param int $length the length of the password
  2017. *
  2018. * @return string the generated password
  2019. */
  2020. function api_generate_password($length = 8)
  2021. {
  2022. if ($length < 2) {
  2023. $length = 2;
  2024. }
  2025. $charactersLowerCase = 'abcdefghijkmnopqrstuvwxyz';
  2026. $charactersUpperCase = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
  2027. $minNumbers = 2;
  2028. $length = $length - $minNumbers;
  2029. $minLowerCase = round($length / 2);
  2030. $minUpperCase = $length - $minLowerCase;
  2031. $password = '';
  2032. $passwordRequirements = api_get_configuration_value('password_requirements');
  2033. $factory = new RandomLib\Factory();
  2034. $generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM));
  2035. if (!empty($passwordRequirements)) {
  2036. $length = $passwordRequirements['min']['length'];
  2037. $minNumbers = $passwordRequirements['min']['numeric'];
  2038. $minLowerCase = $passwordRequirements['min']['lowercase'];
  2039. $minUpperCase = $passwordRequirements['min']['uppercase'];
  2040. $rest = $length - $minNumbers - $minLowerCase - $minUpperCase;
  2041. // Add the rest to fill the length requirement
  2042. if ($rest > 0) {
  2043. $password .= $generator->generateString($rest, $charactersLowerCase.$charactersUpperCase);
  2044. }
  2045. }
  2046. // Min digits default 2
  2047. for ($i = 0; $i < $minNumbers; $i++) {
  2048. $password .= $generator->generateInt(2, 9);
  2049. }
  2050. // Min lowercase
  2051. $password .= $generator->generateString($minLowerCase, $charactersLowerCase);
  2052. // Min uppercase
  2053. $password .= $generator->generateString($minUpperCase, $charactersUpperCase);
  2054. $password = str_shuffle($password);
  2055. return $password;
  2056. }
  2057. /**
  2058. * Checks a password to see wether it is OK to use.
  2059. *
  2060. * @param string $password
  2061. *
  2062. * @return bool if the password is acceptable, false otherwise
  2063. * Notes about what a password "OK to use" is:
  2064. * 1. The password should be at least 5 characters long.
  2065. * 2. Only English letters (uppercase or lowercase, it doesn't matter) and digits are allowed.
  2066. * 3. The password should contain at least 3 letters.
  2067. * 4. It should contain at least 2 digits.
  2068. * Settings will change if the configuration value is set: password_requirements
  2069. */
  2070. function api_check_password($password)
  2071. {
  2072. $passwordRequirements = Security::getPasswordRequirements();
  2073. $minLength = $passwordRequirements['min']['length'];
  2074. $minNumbers = $passwordRequirements['min']['numeric'];
  2075. // Optional
  2076. $minLowerCase = $passwordRequirements['min']['lowercase'];
  2077. $minUpperCase = $passwordRequirements['min']['uppercase'];
  2078. $minLetters = $minLowerCase + $minUpperCase;
  2079. $passwordLength = api_strlen($password);
  2080. $conditions = [
  2081. 'min_length' => $passwordLength >= $minLength,
  2082. ];
  2083. $digits = 0;
  2084. $lowerCase = 0;
  2085. $upperCase = 0;
  2086. for ($i = 0; $i < $passwordLength; $i++) {
  2087. $currentCharacterCode = api_ord(api_substr($password, $i, 1));
  2088. if ($currentCharacterCode >= 65 && $currentCharacterCode <= 90) {
  2089. $upperCase++;
  2090. }
  2091. if ($currentCharacterCode >= 97 && $currentCharacterCode <= 122) {
  2092. $lowerCase++;
  2093. }
  2094. if ($currentCharacterCode >= 48 && $currentCharacterCode <= 57) {
  2095. $digits++;
  2096. }
  2097. }
  2098. // Min number of digits
  2099. $conditions['min_numeric'] = $digits >= $minNumbers;
  2100. if (!empty($minUpperCase)) {
  2101. // Uppercase
  2102. $conditions['min_uppercase'] = $upperCase >= $minUpperCase;
  2103. }
  2104. if (!empty($minLowerCase)) {
  2105. // Lowercase
  2106. $conditions['min_lowercase'] = $upperCase >= $minLowerCase;
  2107. }
  2108. // Min letters
  2109. $letters = $upperCase + $lowerCase;
  2110. $conditions['min_letters'] = $letters >= $minLetters;
  2111. $isPasswordOk = true;
  2112. foreach ($conditions as $condition) {
  2113. if ($condition === false) {
  2114. $isPasswordOk = false;
  2115. break;
  2116. }
  2117. }
  2118. if ($isPasswordOk === false) {
  2119. $output = get_lang('The new password does not match the minimum security requirements').'<br />';
  2120. $output .= Security::getPasswordRequirementsToString($conditions);
  2121. Display::addFlash(Display::return_message($output, 'warning', false));
  2122. }
  2123. return $isPasswordOk;
  2124. }
  2125. /**
  2126. * Returns the status string corresponding to the status code.
  2127. *
  2128. * @author Noel Dieschburg
  2129. *
  2130. * @param the int status code
  2131. *
  2132. * @return string
  2133. */
  2134. function get_status_from_code($status_code)
  2135. {
  2136. switch ($status_code) {
  2137. case STUDENT:
  2138. return get_lang('Student', '');
  2139. case COURSEMANAGER:
  2140. return get_lang('Teacher', '');
  2141. case SESSIONADMIN:
  2142. return get_lang('SessionsAdmin', '');
  2143. case DRH:
  2144. return get_lang('Drh', '');
  2145. }
  2146. }
  2147. /**
  2148. * Gets the current Chamilo (not PHP/cookie) session ID.
  2149. *
  2150. * @return int O if no active session, the session ID otherwise
  2151. */
  2152. function api_get_session_id()
  2153. {
  2154. return (int) Session::read('id_session', 0);
  2155. }
  2156. /**
  2157. * Gets the current Chamilo (not social network) group ID.
  2158. *
  2159. * @return int O if no active session, the session ID otherwise
  2160. */
  2161. function api_get_group_id()
  2162. {
  2163. return Session::read('_gid', 0);
  2164. }
  2165. /**
  2166. * Gets the current or given session name.
  2167. *
  2168. * @param int Session ID (optional)
  2169. *
  2170. * @return string The session name, or null if not found
  2171. */
  2172. function api_get_session_name($session_id = 0)
  2173. {
  2174. if (empty($session_id)) {
  2175. $session_id = api_get_session_id();
  2176. if (empty($session_id)) {
  2177. return null;
  2178. }
  2179. }
  2180. $t = Database::get_main_table(TABLE_MAIN_SESSION);
  2181. $s = "SELECT name FROM $t WHERE id = ".(int) $session_id;
  2182. $r = Database::query($s);
  2183. $c = Database::num_rows($r);
  2184. if ($c > 0) {
  2185. //technically, there can be only one, but anyway we take the first
  2186. $rec = Database::fetch_array($r);
  2187. return $rec['name'];
  2188. }
  2189. return null;
  2190. }
  2191. /**
  2192. * Gets the session info by id.
  2193. *
  2194. * @param int $id Session ID
  2195. *
  2196. * @return array information of the session
  2197. */
  2198. function api_get_session_info($id)
  2199. {
  2200. return SessionManager::fetch($id);
  2201. }
  2202. /**
  2203. * Gets the session visibility by session id.
  2204. *
  2205. * @param int $session_id
  2206. * @param int $courseId
  2207. * @param bool $ignore_visibility_for_admins
  2208. *
  2209. * @return int
  2210. * 0 = session still available,
  2211. * SESSION_VISIBLE_READ_ONLY = 1,
  2212. * SESSION_VISIBLE = 2,
  2213. * SESSION_INVISIBLE = 3
  2214. */
  2215. function api_get_session_visibility(
  2216. $session_id,
  2217. $courseId = null,
  2218. $ignore_visibility_for_admins = true
  2219. ) {
  2220. if (api_is_platform_admin()) {
  2221. if ($ignore_visibility_for_admins) {
  2222. return SESSION_AVAILABLE;
  2223. }
  2224. }
  2225. $now = time();
  2226. if (empty($session_id)) {
  2227. return 0; // Means that the session is still available.
  2228. }
  2229. $session_id = (int) $session_id;
  2230. $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
  2231. $result = Database::query("SELECT * FROM $tbl_session WHERE id = $session_id");
  2232. if (Database::num_rows($result) <= 0) {
  2233. return SESSION_INVISIBLE;
  2234. }
  2235. $row = Database::fetch_array($result, 'ASSOC');
  2236. $visibility = $original_visibility = $row['visibility'];
  2237. // I don't care the session visibility.
  2238. if (empty($row['access_start_date']) && empty($row['access_end_date'])) {
  2239. // Session duration per student.
  2240. if (isset($row['duration']) && !empty($row['duration'])) {
  2241. $duration = $row['duration'] * 24 * 60 * 60;
  2242. $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser($session_id, api_get_user_id());
  2243. // If there is a session duration but there is no previous
  2244. // access by the user, then the session is still available
  2245. if (count($courseAccess) == 0) {
  2246. return SESSION_AVAILABLE;
  2247. }
  2248. $currentTime = time();
  2249. $firstAccess = isset($courseAccess['login_course_date'])
  2250. ? api_strtotime($courseAccess['login_course_date'], 'UTC')
  2251. : 0;
  2252. $userDurationData = SessionManager::getUserSession(
  2253. api_get_user_id(),
  2254. $session_id
  2255. );
  2256. $userDuration = isset($userDurationData['duration'])
  2257. ? (intval($userDurationData['duration']) * 24 * 60 * 60)
  2258. : 0;
  2259. $totalDuration = $firstAccess + $duration + $userDuration;
  2260. return $totalDuration > $currentTime ? SESSION_AVAILABLE : SESSION_VISIBLE_READ_ONLY;
  2261. }
  2262. return SESSION_AVAILABLE;
  2263. }
  2264. // If start date was set.
  2265. if (!empty($row['access_start_date'])) {
  2266. $visibility = $now > api_strtotime($row['access_start_date'], 'UTC') ? SESSION_AVAILABLE : SESSION_INVISIBLE;
  2267. }
  2268. // If the end date was set.
  2269. if (!empty($row['access_end_date'])) {
  2270. // Only if date_start said that it was ok
  2271. if ($visibility === SESSION_AVAILABLE) {
  2272. $visibility = $now < api_strtotime($row['access_end_date'], 'UTC')
  2273. ? SESSION_AVAILABLE // Date still available
  2274. : $row['visibility']; // Session ends
  2275. }
  2276. }
  2277. // If I'm a coach the visibility can change in my favor depending in the coach dates.
  2278. $isCoach = api_is_coach($session_id, $courseId);
  2279. if ($isCoach) {
  2280. // Test start date.
  2281. if (!empty($row['coach_access_start_date'])) {
  2282. $start = api_strtotime($row['coach_access_start_date'], 'UTC');
  2283. $visibility = $start < $now ? SESSION_AVAILABLE : SESSION_INVISIBLE;
  2284. }
  2285. // Test end date.
  2286. if (!empty($row['coach_access_end_date'])) {
  2287. if ($visibility === SESSION_AVAILABLE) {
  2288. $endDateCoach = api_strtotime($row['coach_access_end_date'], 'UTC');
  2289. $visibility = $endDateCoach >= $now ? SESSION_AVAILABLE : $row['visibility'];
  2290. }
  2291. }
  2292. }
  2293. return $visibility;
  2294. }
  2295. /**
  2296. * This function returns a (star) session icon if the session is not null and
  2297. * the user is not a student.
  2298. *
  2299. * @param int $sessionId
  2300. * @param int $statusId User status id - if 5 (student), will return empty
  2301. *
  2302. * @return string Session icon
  2303. */
  2304. function api_get_session_image($sessionId, $statusId)
  2305. {
  2306. $sessionId = (int) $sessionId;
  2307. $image = '';
  2308. if ($statusId != STUDENT) {
  2309. // Check whether is not a student
  2310. if ($sessionId > 0) {
  2311. $image = '&nbsp;&nbsp;'.Display::return_icon(
  2312. 'star.png',
  2313. get_lang('Session-specific resource'),
  2314. ['align' => 'absmiddle'],
  2315. ICON_SIZE_SMALL
  2316. );
  2317. }
  2318. }
  2319. return $image;
  2320. }
  2321. /**
  2322. * This function add an additional condition according to the session of the course.
  2323. *
  2324. * @param int $session_id session id
  2325. * @param bool $and optional, true if more than one condition false if the only condition in the query
  2326. * @param bool $with_base_content optional, true to accept content with session=0 as well,
  2327. * false for strict session condition
  2328. * @param string $session_field
  2329. *
  2330. * @return string condition of the session
  2331. */
  2332. function api_get_session_condition(
  2333. $session_id,
  2334. $and = true,
  2335. $with_base_content = false,
  2336. $session_field = 'session_id'
  2337. ) {
  2338. $session_id = (int) $session_id;
  2339. if (empty($session_field)) {
  2340. $session_field = 'session_id';
  2341. }
  2342. // Condition to show resources by session
  2343. $condition_add = $and ? ' AND ' : ' WHERE ';
  2344. if ($with_base_content) {
  2345. $condition_session = $condition_add." ( $session_field = $session_id OR $session_field = 0 OR $session_field IS NULL) ";
  2346. } else {
  2347. if (empty($session_id)) {
  2348. $condition_session = $condition_add." ($session_field = $session_id OR $session_field IS NULL)";
  2349. } else {
  2350. $condition_session = $condition_add." $session_field = $session_id ";
  2351. }
  2352. }
  2353. return $condition_session;
  2354. }
  2355. /**
  2356. * Returns the value of a setting from the web-adjustable admin config settings.
  2357. *
  2358. * WARNING true/false are stored as string, so when comparing you need to check e.g.
  2359. * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
  2360. * instead of
  2361. * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
  2362. *
  2363. * @param string $variable The variable name
  2364. *
  2365. * @return string
  2366. */
  2367. function api_get_setting($variable)
  2368. {
  2369. $settingsManager = Container::getSettingsManager();
  2370. if (empty($settingsManager)) {
  2371. return '';
  2372. }
  2373. $variable = trim($variable);
  2374. switch ($variable) {
  2375. case 'header_extra_content':
  2376. $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
  2377. if (file_exists($filename)) {
  2378. $value = file_get_contents($filename);
  2379. return $value;
  2380. } else {
  2381. return '';
  2382. }
  2383. break;
  2384. case 'footer_extra_content':
  2385. $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
  2386. if (file_exists($filename)) {
  2387. $value = file_get_contents($filename);
  2388. return $value;
  2389. } else {
  2390. return '';
  2391. }
  2392. break;
  2393. case 'server_type':
  2394. $test = ['dev', 'test'];
  2395. $environment = Container::getEnvironment();
  2396. if (in_array($environment, $test)) {
  2397. return 'test';
  2398. }
  2399. return 'prod';
  2400. case 'stylesheets':
  2401. $variable = 'platform.theme';
  2402. // deprecated settings
  2403. // no break
  2404. case 'openid_authentication':
  2405. case 'service_ppt2lp':
  2406. case 'formLogin_hide_unhide_label':
  2407. return false;
  2408. break;
  2409. case 'tool_visible_by_default_at_creation':
  2410. $values = $settingsManager->getSetting($variable);
  2411. $newResult = [];
  2412. foreach ($values as $parameter) {
  2413. $newResult[$parameter] = 'true';
  2414. }
  2415. return $newResult;
  2416. break;
  2417. default:
  2418. return $settingsManager->getSetting($variable);
  2419. break;
  2420. }
  2421. global $_setting;
  2422. if ($variable == 'header_extra_content') {
  2423. $filename = api_get_home_path().'header_extra_content.txt';
  2424. if (file_exists($filename)) {
  2425. $value = file_get_contents($filename);
  2426. return $value;
  2427. } else {
  2428. return '';
  2429. }
  2430. }
  2431. if ($variable == 'footer_extra_content') {
  2432. $filename = api_get_home_path().'footer_extra_content.txt';
  2433. if (file_exists($filename)) {
  2434. $value = file_get_contents($filename);
  2435. return $value;
  2436. } else {
  2437. return '';
  2438. }
  2439. }
  2440. $value = null;
  2441. if (is_null($key)) {
  2442. $value = ((isset($_setting[$variable]) && $_setting[$variable] != '') ? $_setting[$variable] : null);
  2443. } else {
  2444. if (isset($_setting[$variable][$key])) {
  2445. $value = $_setting[$variable][$key];
  2446. }
  2447. }
  2448. return $value;
  2449. }
  2450. /**
  2451. * @param string $variable
  2452. * @param string $option
  2453. *
  2454. * @return bool
  2455. */
  2456. function api_get_setting_in_list($variable, $option)
  2457. {
  2458. $value = api_get_setting($variable);
  2459. return in_array($option, $value);
  2460. }
  2461. /**
  2462. * @param string $plugin
  2463. * @param string $variable
  2464. *
  2465. * @return string
  2466. */
  2467. function api_get_plugin_setting($plugin, $variable)
  2468. {
  2469. $variableName = $plugin.'_'.$variable;
  2470. $params = [
  2471. 'category = ? AND subkey = ? AND variable = ?' => [
  2472. 'Plugins',
  2473. $plugin,
  2474. $variableName,
  2475. ],
  2476. ];
  2477. $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2478. $result = Database::select(
  2479. 'selected_value',
  2480. $table,
  2481. ['where' => $params],
  2482. 'one'
  2483. );
  2484. if ($result) {
  2485. $value = $result['selected_value'];
  2486. $serializedValue = @unserialize($result['selected_value'], []);
  2487. if ($serializedValue !== false) {
  2488. $value = $serializedValue;
  2489. }
  2490. return $value;
  2491. }
  2492. return null;
  2493. /// Old code
  2494. $variableName = $plugin.'_'.$variable;
  2495. $result = api_get_setting($variableName);
  2496. if (isset($result[$plugin])) {
  2497. $value = $result[$plugin];
  2498. $unserialized = UnserializeApi::unserialize('not_allowed_classes', $value, true);
  2499. if (false !== $unserialized) {
  2500. $value = $unserialized;
  2501. }
  2502. return $value;
  2503. }
  2504. return null;
  2505. }
  2506. /**
  2507. * Returns the value of a setting from the web-adjustable admin config settings.
  2508. */
  2509. function api_get_settings_params($params)
  2510. {
  2511. $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2512. $result = Database::select('*', $table, ['where' => $params]);
  2513. return $result;
  2514. }
  2515. /**
  2516. * @param array $params example: [id = ? => '1']
  2517. *
  2518. * @return array
  2519. */
  2520. function api_get_settings_params_simple($params)
  2521. {
  2522. $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2523. $result = Database::select('*', $table, ['where' => $params], 'one');
  2524. return $result;
  2525. }
  2526. /**
  2527. * Returns the value of a setting from the web-adjustable admin config settings.
  2528. */
  2529. function api_delete_settings_params($params)
  2530. {
  2531. $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2532. $result = Database::delete($table, $params);
  2533. return $result;
  2534. }
  2535. /**
  2536. * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection.
  2537. *
  2538. * @return string Escaped version of $_SERVER['PHP_SELF']
  2539. */
  2540. function api_get_self()
  2541. {
  2542. return htmlentities($_SERVER['PHP_SELF']);
  2543. }
  2544. /* USER PERMISSIONS */
  2545. /**
  2546. * Checks whether current user is a platform administrator.
  2547. *
  2548. * @param bool $allowSessionAdmins Whether session admins should be considered admins or not
  2549. * @param bool $allowDrh Whether HR directors should be considered admins or not
  2550. *
  2551. * @return bool true if the user has platform admin rights,
  2552. * false otherwise
  2553. *
  2554. * @see usermanager::is_admin(user_id) for a user-id specific function
  2555. */
  2556. function api_is_platform_admin($allowSessionAdmins = false, $allowDrh = false)
  2557. {
  2558. $currentUser = api_get_current_user();
  2559. if ($currentUser === null) {
  2560. return false;
  2561. }
  2562. $isAdmin = Session::read('is_platformAdmin');
  2563. if ($isAdmin) {
  2564. return true;
  2565. }
  2566. $user = api_get_user_info();
  2567. return
  2568. isset($user['status']) &&
  2569. (
  2570. ($allowSessionAdmins && $user['status'] == SESSIONADMIN) ||
  2571. ($allowDrh && $user['status'] == DRH)
  2572. );
  2573. }
  2574. /**
  2575. * Checks whether the user given as user id is in the admin table.
  2576. *
  2577. * @param int $user_id If none provided, will use current user
  2578. * @param int $url URL ID. If provided, also check if the user is active on given URL
  2579. *
  2580. * @return bool True if the user is admin, false otherwise
  2581. */
  2582. function api_is_platform_admin_by_id($user_id = null, $url = null)
  2583. {
  2584. $user_id = (int) $user_id;
  2585. if (empty($user_id)) {
  2586. $user_id = api_get_user_id();
  2587. }
  2588. $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
  2589. $sql = "SELECT * FROM $admin_table WHERE user_id = $user_id";
  2590. $res = Database::query($sql);
  2591. $is_admin = Database::num_rows($res) === 1;
  2592. if (!$is_admin || !isset($url)) {
  2593. return $is_admin;
  2594. }
  2595. // We get here only if $url is set
  2596. $url = (int) $url;
  2597. $url_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
  2598. $sql = "SELECT * FROM $url_user_table
  2599. WHERE access_url_id = $url AND user_id = $user_id";
  2600. $res = Database::query($sql);
  2601. $result = Database::num_rows($res) === 1;
  2602. return $result;
  2603. }
  2604. /**
  2605. * Returns the user's numeric status ID from the users table.
  2606. *
  2607. * @param int $user_id If none provided, will use current user
  2608. *
  2609. * @return int User's status (1 for teacher, 5 for student, etc)
  2610. */
  2611. function api_get_user_status($user_id = null)
  2612. {
  2613. $user_id = (int) $user_id;
  2614. if (empty($user_id)) {
  2615. $user_id = api_get_user_id();
  2616. }
  2617. $table = Database::get_main_table(TABLE_MAIN_USER);
  2618. $sql = "SELECT status FROM $table WHERE user_id = $user_id ";
  2619. $result = Database::query($sql);
  2620. $status = null;
  2621. if (Database::num_rows($result)) {
  2622. $row = Database::fetch_array($result);
  2623. $status = $row['status'];
  2624. }
  2625. return $status;
  2626. }
  2627. /**
  2628. * Checks whether current user is allowed to create courses.
  2629. *
  2630. * @return bool true if the user has course creation rights,
  2631. * false otherwise
  2632. */
  2633. function api_is_allowed_to_create_course()
  2634. {
  2635. if (api_is_platform_admin()) {
  2636. return true;
  2637. }
  2638. // Teachers can only create courses
  2639. if (api_is_teacher()) {
  2640. if (api_get_setting('allow_users_to_create_courses') === 'true') {
  2641. return true;
  2642. } else {
  2643. return false;
  2644. }
  2645. }
  2646. return Session::read('is_allowedCreateCourse');
  2647. }
  2648. /**
  2649. * Checks whether the current user is a course administrator.
  2650. *
  2651. * @return bool True if current user is a course administrator
  2652. */
  2653. function api_is_course_admin()
  2654. {
  2655. if (api_is_platform_admin()) {
  2656. return true;
  2657. }
  2658. $user = api_get_current_user();
  2659. if ($user) {
  2660. if (
  2661. $user->hasRole('ROLE_CURRENT_SESSION_COURSE_TEACHER') ||
  2662. $user->hasRole('ROLE_CURRENT_COURSE_TEACHER')
  2663. ) {
  2664. return true;
  2665. }
  2666. }
  2667. return false;
  2668. //return Session::read('is_courseAdmin');
  2669. }
  2670. /**
  2671. * Checks whether the current user is a course coach
  2672. * Based on the presence of user in session.id_coach (session general coach).
  2673. *
  2674. * @return bool True if current user is a course coach
  2675. */
  2676. function api_is_session_general_coach()
  2677. {
  2678. return Session::read('is_session_general_coach');
  2679. }
  2680. /**
  2681. * Checks whether the current user is a course tutor
  2682. * Based on the presence of user in session_rel_course_rel_user.user_id with status = 2.
  2683. *
  2684. * @return bool True if current user is a course tutor
  2685. */
  2686. function api_is_course_tutor()
  2687. {
  2688. return Session::read('is_courseTutor');
  2689. }
  2690. /**
  2691. * @param int $user_id
  2692. * @param int $courseId
  2693. * @param int $session_id
  2694. *
  2695. * @return bool
  2696. */
  2697. function api_is_course_session_coach($user_id, $courseId, $session_id)
  2698. {
  2699. $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
  2700. $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
  2701. $user_id = (int) $user_id;
  2702. $session_id = (int) $session_id;
  2703. $courseId = (int) $courseId;
  2704. $sql = "SELECT DISTINCT session.id
  2705. FROM $session_table
  2706. INNER JOIN $session_rel_course_rel_user_table session_rc_ru
  2707. ON session.id = session_rc_ru.session_id
  2708. WHERE
  2709. session_rc_ru.user_id = '".$user_id."' AND
  2710. session_rc_ru.c_id = '$courseId' AND
  2711. session_rc_ru.status = 2 AND
  2712. session_rc_ru.session_id = '$session_id'";
  2713. $result = Database::query($sql);
  2714. return Database::num_rows($result) > 0;
  2715. }
  2716. /**
  2717. * Checks whether the current user is a course or session coach.
  2718. *
  2719. * @param int $session_id
  2720. * @param int $courseId
  2721. * @param bool Check whether we are in student view and, if we are, return false
  2722. *
  2723. * @return bool True if current user is a course or session coach
  2724. */
  2725. function api_is_coach($session_id = 0, $courseId = null, $check_student_view = true)
  2726. {
  2727. $userId = api_get_user_id();
  2728. if (!empty($session_id)) {
  2729. $session_id = (int) $session_id;
  2730. } else {
  2731. $session_id = api_get_session_id();
  2732. }
  2733. // The student preview was on
  2734. if ($check_student_view && api_is_student_view_active()) {
  2735. return false;
  2736. }
  2737. if (!empty($courseId)) {
  2738. $courseId = (int) $courseId;
  2739. } else {
  2740. $courseId = api_get_course_int_id();
  2741. }
  2742. $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
  2743. $session_rel_course_rel_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
  2744. $sessionIsCoach = [];
  2745. if (!empty($courseId)) {
  2746. $sql = "SELECT DISTINCT s.id, name, access_start_date, access_end_date
  2747. FROM $session_table s
  2748. INNER JOIN $session_rel_course_rel_user_table session_rc_ru
  2749. ON session_rc_ru.session_id = s.id AND session_rc_ru.user_id = '".$userId."'
  2750. WHERE
  2751. session_rc_ru.c_id = '$courseId' AND
  2752. session_rc_ru.status = 2 AND
  2753. session_rc_ru.session_id = '$session_id'";
  2754. $result = Database::query($sql);
  2755. $sessionIsCoach = Database::store_result($result);
  2756. }
  2757. if (!empty($session_id)) {
  2758. $sql = "SELECT DISTINCT id, name, access_start_date, access_end_date
  2759. FROM $session_table
  2760. WHERE session.id_coach = $userId AND id = $session_id
  2761. ORDER BY access_start_date, access_end_date, name";
  2762. $result = Database::query($sql);
  2763. if (!empty($sessionIsCoach)) {
  2764. $sessionIsCoach = array_merge(
  2765. $sessionIsCoach,
  2766. Database::store_result($result)
  2767. );
  2768. } else {
  2769. $sessionIsCoach = Database::store_result($result);
  2770. }
  2771. }
  2772. return count($sessionIsCoach) > 0;
  2773. }
  2774. /**
  2775. * Checks whether the current user is a session administrator.
  2776. *
  2777. * @return bool True if current user is a course administrator
  2778. */
  2779. function api_is_session_admin()
  2780. {
  2781. $user = api_get_user_info();
  2782. return isset($user['status']) && $user['status'] == SESSIONADMIN;
  2783. }
  2784. /**
  2785. * Checks whether the current user is a human resources manager.
  2786. *
  2787. * @return bool True if current user is a human resources manager
  2788. */
  2789. function api_is_drh()
  2790. {
  2791. $user = api_get_user_info();
  2792. return isset($user['status']) && $user['status'] == DRH;
  2793. }
  2794. /**
  2795. * Checks whether the current user is a student.
  2796. *
  2797. * @return bool True if current user is a human resources manager
  2798. */
  2799. function api_is_student()
  2800. {
  2801. $user = api_get_user_info();
  2802. return isset($user['status']) && $user['status'] == STUDENT;
  2803. }
  2804. /**
  2805. * Checks whether the current user has the status 'teacher'.
  2806. *
  2807. * @return bool True if current user is a human resources manager
  2808. */
  2809. function api_is_teacher()
  2810. {
  2811. $user = api_get_user_info();
  2812. return isset($user['status']) && $user['status'] == COURSEMANAGER;
  2813. }
  2814. /**
  2815. * Checks whether the current user is a invited user.
  2816. *
  2817. * @return bool
  2818. */
  2819. function api_is_invitee()
  2820. {
  2821. $user = api_get_user_info();
  2822. return isset($user['status']) && $user['status'] == INVITEE;
  2823. }
  2824. /**
  2825. * This function checks whether a session is assigned into a category.
  2826. *
  2827. * @param int - session id
  2828. * @param string - category name
  2829. *
  2830. * @return bool - true if is found, otherwise false
  2831. */
  2832. function api_is_session_in_category($session_id, $category_name)
  2833. {
  2834. $session_id = (int) $session_id;
  2835. $category_name = Database::escape_string($category_name);
  2836. $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
  2837. $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
  2838. $sql = "SELECT 1
  2839. FROM $tbl_session
  2840. WHERE $session_id IN (
  2841. SELECT s.id FROM $tbl_session s, $tbl_session_category sc
  2842. WHERE
  2843. s.session_category_id = sc.id AND
  2844. sc.name LIKE '%$category_name'
  2845. )";
  2846. $rs = Database::query($sql);
  2847. if (Database::num_rows($rs) > 0) {
  2848. return true;
  2849. } else {
  2850. return false;
  2851. }
  2852. }
  2853. /**
  2854. * Displays the title of a tool.
  2855. * Normal use: parameter is a string:
  2856. * api_display_tool_title("My Tool").
  2857. *
  2858. * Optionally, there can be a subtitle below
  2859. * the normal title, and / or a supra title above the normal title.
  2860. *
  2861. * e.g. supra title:
  2862. * group
  2863. * GROUP PROPERTIES
  2864. *
  2865. * e.g. subtitle:
  2866. * AGENDA
  2867. * calender & events tool
  2868. *
  2869. * @author Hugues Peeters <hugues.peeters@claroline.net>
  2870. *
  2871. * @param mixed $title_element - it could either be a string or an array
  2872. * containing 'supraTitle', 'mainTitle',
  2873. * 'subTitle'
  2874. */
  2875. function api_display_tool_title($title_element)
  2876. {
  2877. if (is_string($title_element)) {
  2878. $tit = $title_element;
  2879. unset($title_element);
  2880. $title_element['mainTitle'] = $tit;
  2881. }
  2882. echo '<h3>';
  2883. if (!empty($title_element['supraTitle'])) {
  2884. echo '<small>'.$title_element['supraTitle'].'</small><br />';
  2885. }
  2886. if (!empty($title_element['mainTitle'])) {
  2887. echo $title_element['mainTitle'];
  2888. }
  2889. if (!empty($title_element['subTitle'])) {
  2890. echo '<br /><small>'.$title_element['subTitle'].'</small>';
  2891. }
  2892. echo '</h3>';
  2893. }
  2894. /**
  2895. * Displays options for switching between student view and course manager view.
  2896. *
  2897. * Changes in version 1.2 (Patrick Cool)
  2898. * Student view switch now behaves as a real switch. It maintains its current state until the state
  2899. * is changed explicitly
  2900. *
  2901. * Changes in version 1.1 (Patrick Cool)
  2902. * student view now works correctly in subfolders of the document tool
  2903. * student view works correctly in the new links tool
  2904. *
  2905. * Example code for using this in your tools:
  2906. * //if ($is_courseAdmin && api_get_setting('student_view_enabled') == 'true') {
  2907. * // display_tool_view_option($isStudentView);
  2908. * //}
  2909. * //and in later sections, use api_is_allowed_to_edit()
  2910. *
  2911. * @author Roan Embrechts
  2912. * @author Patrick Cool
  2913. * @author Julio Montoya, changes added in Chamilo
  2914. *
  2915. * @version 1.2
  2916. *
  2917. * @todo rewrite code so it is easier to understand
  2918. */
  2919. function api_display_tool_view_option()
  2920. {
  2921. if (api_get_setting('student_view_enabled') != 'true') {
  2922. return '';
  2923. }
  2924. $sourceurl = '';
  2925. $is_framed = false;
  2926. // Exceptions apply for all multi-frames pages
  2927. if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) {
  2928. // The chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
  2929. return '';
  2930. }
  2931. // Uncomment to remove student view link from document view page
  2932. if (strpos($_SERVER['REQUEST_URI'], 'lp/lp_header.php') !== false) {
  2933. if (empty($_GET['lp_id'])) {
  2934. return '';
  2935. }
  2936. $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
  2937. $sourceurl = str_replace(
  2938. 'lp/lp_header.php',
  2939. 'lp/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.intval($_GET['lp_id']).'&isStudentView='.($_SESSION['studentview'] == 'studentview' ? 'false' : 'true'),
  2940. $sourceurl
  2941. );
  2942. //showinframes doesn't handle student view anyway...
  2943. //return '';
  2944. $is_framed = true;
  2945. }
  2946. // Check whether the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
  2947. if (!$is_framed) {
  2948. if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
  2949. $sourceurl = api_get_self().'?'.api_get_cidreq();
  2950. } else {
  2951. $sourceurl = $_SERVER['REQUEST_URI'];
  2952. }
  2953. }
  2954. $output_string = '';
  2955. if (!empty($_SESSION['studentview'])) {
  2956. if ($_SESSION['studentview'] == 'studentview') {
  2957. // We have to remove the isStudentView=true from the $sourceurl
  2958. $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
  2959. $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
  2960. $output_string .= '<a class="btn btn-primary btn-sm" href="'.$sourceurl.'&isStudentView=false" target="_self">'.
  2961. Display::returnFontAwesomeIcon('eye').' '.get_lang('Switch to teacher view').'</a>';
  2962. } elseif ($_SESSION['studentview'] == 'teacherview') {
  2963. // Switching to teacherview
  2964. $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
  2965. $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
  2966. $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.
  2967. Display::returnFontAwesomeIcon('eye').' '.get_lang('Switch to student view').'</a>';
  2968. }
  2969. } else {
  2970. $output_string .= '<a class="btn btn-default btn-sm" href="'.$sourceurl.'&isStudentView=true" target="_self">'.
  2971. Display::returnFontAwesomeIcon('eye').' '.get_lang('Switch to student view').'</a>';
  2972. }
  2973. $output_string = Security::remove_XSS($output_string);
  2974. $html = Display::tag('div', $output_string, ['class' => 'view-options']);
  2975. return $html;
  2976. }
  2977. // TODO: This is for the permission section.
  2978. /**
  2979. * Function that removes the need to directly use is_courseAdmin global in
  2980. * tool scripts. It returns true or false depending on the user's rights in
  2981. * this particular course.
  2982. * Optionally checking for tutor and coach roles here allows us to use the
  2983. * student_view feature altogether with these roles as well.
  2984. *
  2985. * @param bool Whether to check if the user has the tutor role
  2986. * @param bool Whether to check if the user has the coach role
  2987. * @param bool Whether to check if the user has the session coach role
  2988. * @param bool check the student view or not
  2989. *
  2990. * @author Roan Embrechts
  2991. * @author Patrick Cool
  2992. * @author Julio Montoya
  2993. *
  2994. * @version 1.1, February 2004
  2995. *
  2996. * @return bool true: the user has the rights to edit, false: he does not
  2997. */
  2998. function api_is_allowed_to_edit(
  2999. $tutor = false,
  3000. $coach = false,
  3001. $session_coach = false,
  3002. $check_student_view = true
  3003. ) {
  3004. $allowSessionAdminEdit = api_get_setting('session.session_admins_edit_courses_content') === true;
  3005. // Admins can edit anything.
  3006. if (api_is_platform_admin($allowSessionAdminEdit)) {
  3007. //The student preview was on
  3008. if ($check_student_view && api_is_student_view_active()) {
  3009. return false;
  3010. } else {
  3011. return true;
  3012. }
  3013. }
  3014. $sessionId = api_get_session_id();
  3015. if ($sessionId && api_get_configuration_value('session_courses_read_only_mode')) {
  3016. $efv = new ExtraFieldValue('course');
  3017. $lockExrafieldField = $efv->get_values_by_handler_and_field_variable(
  3018. api_get_course_int_id(),
  3019. 'session_courses_read_only_mode'
  3020. );
  3021. if (!empty($lockExrafieldField['value'])) {
  3022. return false;
  3023. }
  3024. }
  3025. $is_allowed_coach_to_edit = api_is_coach(null, null, $check_student_view);
  3026. $session_visibility = api_get_session_visibility($sessionId);
  3027. $is_courseAdmin = api_is_course_admin();
  3028. if (!$is_courseAdmin && $tutor) {
  3029. // If we also want to check if the user is a tutor...
  3030. $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
  3031. }
  3032. if (!$is_courseAdmin && $coach) {
  3033. // If we also want to check if the user is a coach...';
  3034. // Check if session visibility is read only for coaches.
  3035. if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
  3036. $is_allowed_coach_to_edit = false;
  3037. }
  3038. if (api_get_setting('allow_coach_to_edit_course_session') === 'true') {
  3039. // Check if coach is allowed to edit a course.
  3040. $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
  3041. }
  3042. }
  3043. if (!$is_courseAdmin && $session_coach) {
  3044. $is_courseAdmin = $is_courseAdmin || $is_allowed_coach_to_edit;
  3045. }
  3046. // Check if the student_view is enabled, and if so, if it is activated.
  3047. if (api_get_setting('student_view_enabled') === 'true') {
  3048. $studentView = api_is_student_view_active();
  3049. if (!empty($sessionId)) {
  3050. // Check if session visibility is read only for coaches.
  3051. if ($session_visibility == SESSION_VISIBLE_READ_ONLY) {
  3052. $is_allowed_coach_to_edit = false;
  3053. }
  3054. $is_allowed = false;
  3055. if (api_get_setting('allow_coach_to_edit_course_session') === 'true') {
  3056. // Check if coach is allowed to edit a course.
  3057. $is_allowed = $is_allowed_coach_to_edit;
  3058. }
  3059. if ($check_student_view) {
  3060. $is_allowed = $is_allowed && $studentView === false;
  3061. }
  3062. } else {
  3063. $is_allowed = $is_courseAdmin;
  3064. if ($check_student_view) {
  3065. $is_allowed = $is_courseAdmin && $studentView === false;
  3066. }
  3067. }
  3068. return $is_allowed;
  3069. } else {
  3070. return $is_courseAdmin;
  3071. }
  3072. }
  3073. /**
  3074. * Returns true if user is a course coach of at least one course in session.
  3075. *
  3076. * @param int $sessionId
  3077. *
  3078. * @return bool
  3079. */
  3080. function api_is_coach_of_course_in_session($sessionId)
  3081. {
  3082. if (api_is_platform_admin()) {
  3083. return true;
  3084. }
  3085. $userId = api_get_user_id();
  3086. $courseList = UserManager::get_courses_list_by_session(
  3087. $userId,
  3088. $sessionId
  3089. );
  3090. // Session visibility.
  3091. $visibility = api_get_session_visibility(
  3092. $sessionId,
  3093. null,
  3094. false
  3095. );
  3096. if ($visibility != SESSION_VISIBLE && !empty($courseList)) {
  3097. // Course Coach session visibility.
  3098. $blockedCourseCount = 0;
  3099. $closedVisibilityList = [
  3100. COURSE_VISIBILITY_CLOSED,
  3101. COURSE_VISIBILITY_HIDDEN,
  3102. ];
  3103. foreach ($courseList as $course) {
  3104. // Checking session visibility
  3105. $sessionCourseVisibility = api_get_session_visibility(
  3106. $sessionId,
  3107. $course['real_id']
  3108. );
  3109. $courseIsVisible = !in_array(
  3110. $course['visibility'],
  3111. $closedVisibilityList
  3112. );
  3113. if ($courseIsVisible === false || $sessionCourseVisibility == SESSION_INVISIBLE) {
  3114. $blockedCourseCount++;
  3115. }
  3116. }
  3117. // If all courses are blocked then no show in the list.
  3118. if ($blockedCourseCount === count($courseList)) {
  3119. $visibility = SESSION_INVISIBLE;
  3120. } else {
  3121. $visibility = SESSION_VISIBLE;
  3122. }
  3123. }
  3124. switch ($visibility) {
  3125. case SESSION_VISIBLE_READ_ONLY:
  3126. case SESSION_VISIBLE:
  3127. case SESSION_AVAILABLE:
  3128. return true;
  3129. break;
  3130. case SESSION_INVISIBLE:
  3131. return false;
  3132. }
  3133. return false;
  3134. }
  3135. /**
  3136. * Checks if a student can edit contents in a session depending
  3137. * on the session visibility.
  3138. *
  3139. * @param bool $tutor Whether to check if the user has the tutor role
  3140. * @param bool $coach Whether to check if the user has the coach role
  3141. *
  3142. * @return bool true: the user has the rights to edit, false: he does not
  3143. */
  3144. function api_is_allowed_to_session_edit($tutor = false, $coach = false)
  3145. {
  3146. if (api_is_allowed_to_edit($tutor, $coach)) {
  3147. // If I'm a teacher, I will return true in order to not affect the normal behaviour of Chamilo tools.
  3148. return true;
  3149. } else {
  3150. $sessionId = api_get_session_id();
  3151. if ($sessionId == 0) {
  3152. // I'm not in a session so i will return true to not affect the normal behaviour of Chamilo tools.
  3153. return true;
  3154. } else {
  3155. // I'm in a session and I'm a student
  3156. // Get the session visibility
  3157. $session_visibility = api_get_session_visibility($sessionId);
  3158. // if 5 the session is still available
  3159. switch ($session_visibility) {
  3160. case SESSION_VISIBLE_READ_ONLY: // 1
  3161. return false;
  3162. case SESSION_VISIBLE: // 2
  3163. return true;
  3164. case SESSION_INVISIBLE: // 3
  3165. return false;
  3166. case SESSION_AVAILABLE: //5
  3167. return true;
  3168. }
  3169. }
  3170. }
  3171. }
  3172. /**
  3173. * Checks whether the user is allowed in a specific tool for a specific action.
  3174. *
  3175. * @param string $tool the tool we are checking if the user has a certain permission
  3176. * @param string $action the action we are checking (add, edit, delete, move, visibility)
  3177. *
  3178. * @return bool
  3179. *
  3180. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  3181. * @author Julio Montoya
  3182. *
  3183. * @version 1.0
  3184. */
  3185. function api_is_allowed($tool, $action, $task_id = 0)
  3186. {
  3187. $_user = api_get_user_info();
  3188. $_course = api_get_course_info();
  3189. if (api_is_course_admin()) {
  3190. return true;
  3191. }
  3192. if (is_array($_course) and count($_course) > 0) {
  3193. require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
  3194. // Getting the permissions of this user.
  3195. if ($task_id == 0) {
  3196. $user_permissions = get_permissions('user', $_user['user_id']);
  3197. $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
  3198. }
  3199. // Getting the permissions of the task.
  3200. if ($task_id != 0) {
  3201. $task_permissions = get_permissions('task', $task_id);
  3202. /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
  3203. }
  3204. //print_r($_SESSION['total_permissions']);
  3205. // Getting the permissions of the groups of the user
  3206. //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
  3207. //foreach($groups_of_user as $group)
  3208. // $this_group_permissions = get_permissions('group', $group);
  3209. // Getting the permissions of the courseroles of the user
  3210. $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
  3211. // Getting the permissions of the platformroles of the user
  3212. //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
  3213. // Getting the permissions of the roles of the groups of the user
  3214. //foreach($groups_of_user as $group)
  3215. // $this_group_courserole_permissions = get_roles_permissions('group', $group);
  3216. // Getting the permissions of the platformroles of the groups of the user
  3217. //foreach($groups_of_user as $group)
  3218. // $this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
  3219. }
  3220. // If the permissions are limited, we have to map the extended ones to the limited ones.
  3221. if (api_get_setting('permissions') == 'limited') {
  3222. if ($action == 'Visibility') {
  3223. $action = 'Edit';
  3224. }
  3225. if ($action == 'Move') {
  3226. $action = 'Edit';
  3227. }
  3228. }
  3229. // The session that contains all the permissions already exists for this course
  3230. // so there is no need to requery everything.
  3231. //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
  3232. if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
  3233. if (in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool])) {
  3234. return true;
  3235. } else {
  3236. return false;
  3237. }
  3238. }
  3239. }
  3240. /**
  3241. * Tells whether this user is an anonymous user.
  3242. *
  3243. * @param int $user_id User ID (optional, will take session ID if not provided)
  3244. * @param bool $db_check Whether to check in the database (true) or simply in
  3245. * the session (false) to see if the current user is the anonymous user
  3246. *
  3247. * @return bool true if this user is anonymous, false otherwise
  3248. */
  3249. function api_is_anonymous($user_id = null, $db_check = false)
  3250. {
  3251. if ($db_check) {
  3252. if (!isset($user_id)) {
  3253. $user_id = api_get_user_id();
  3254. }
  3255. $info = api_get_user_info($user_id);
  3256. if ($info['status'] == 6 || $user_id == 0 || empty($info)) {
  3257. return true;
  3258. }
  3259. }
  3260. return !Container::getAuthorizationChecker()->isGranted('IS_AUTHENTICATED_FULLY');
  3261. }
  3262. /**
  3263. * Displays message "You are not allowed here..." and exits the entire script.
  3264. *
  3265. * @param bool $print_headers Whether or not to print headers (default = false -> does not print them)
  3266. * @param string $message
  3267. * @param int $responseCode
  3268. */
  3269. function api_not_allowed(
  3270. $print_headers = false,
  3271. $message = null,
  3272. $responseCode = 0
  3273. ) {
  3274. $debug = api_get_setting('server_type') === 'test';
  3275. // Default code is 403 forbidden
  3276. $responseCode = empty($responseCode) ? 403 : $responseCode;
  3277. $message = empty($message) ? get_lang('Not authorized') : $message;
  3278. // Create new exception rendered by template:
  3279. // src/ThemeBundle/Resources/views/Exception/error.html.twig
  3280. // if error is 404 then the template is:
  3281. // src/ThemeBundle/Resources/views/Exception/error404.html.twig
  3282. $exception = new Exception($message);
  3283. $request = Container::getRequest();
  3284. $exception = FlattenException::create($exception, $responseCode);
  3285. $controller = new ExceptionController(Container::getTwig(), $debug);
  3286. $response = $controller->showAction($request, $exception);
  3287. $response->send();
  3288. exit;
  3289. $home_url = api_get_path(WEB_PATH);
  3290. $user_id = api_get_user_id();
  3291. $course = api_get_course_id();
  3292. global $this_section;
  3293. if (CustomPages::enabled() && !isset($user_id)) {
  3294. if (empty($user_id)) {
  3295. // Why the CustomPages::enabled() need to be to set the request_uri
  3296. $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
  3297. }
  3298. CustomPages::display(CustomPages::INDEX_UNLOGGED);
  3299. }
  3300. $origin = api_get_origin();
  3301. $msg = null;
  3302. if (isset($message)) {
  3303. $msg = $message;
  3304. } else {
  3305. $msg = Display::return_message(
  3306. get_lang('Sorry, you are not allowed to access this page, or maybe your connection has expired. Please click your browser\'s "Back" button or follow the link below to return to the previous page.').'
  3307. <script>function goBack(){window.history.back();}</script>',
  3308. 'error',
  3309. false
  3310. );
  3311. $msg .= '<p class="text-center">
  3312. <a onclick="goBack();" class="btn btn-default" href="'.$home_url.'">'.get_lang('Go back').'</a>
  3313. </p>';
  3314. }
  3315. $msg = Display::div($msg, ['align' => 'center']);
  3316. $show_headers = 0;
  3317. if ($print_headers && $origin != 'learnpath') {
  3318. $show_headers = 1;
  3319. }
  3320. $tpl = new Template(null, $show_headers, $show_headers, false, true, false, true, $responseCode);
  3321. $tpl->assign('hide_login_link', 1);
  3322. $tpl->assign('content', $msg);
  3323. if (($user_id != 0 && !api_is_anonymous()) &&
  3324. (!isset($course) || $course == -1) &&
  3325. empty($_GET['cidReq'])
  3326. ) {
  3327. // if the access is not authorized and there is some login information
  3328. // but the cidReq is not found, assume we are missing course data and send the user
  3329. // to the user_portal
  3330. $tpl->display_one_col_template();
  3331. exit;
  3332. }
  3333. if (!empty($_SERVER['REQUEST_URI']) &&
  3334. (
  3335. !empty($_GET['cidReq']) ||
  3336. $this_section == SECTION_MYPROFILE ||
  3337. $this_section == SECTION_PLATFORM_ADMIN
  3338. )
  3339. ) {
  3340. $courseCode = api_get_course_id();
  3341. // Only display form and return to the previous URL if there was a course ID included
  3342. if ($user_id != 0 && !api_is_anonymous()) {
  3343. //if there is a user ID, then the user is not allowed but the session is still there. Say so and exit
  3344. $tpl->assign('content', $msg);
  3345. $tpl->display_one_col_template();
  3346. exit;
  3347. }
  3348. if (!is_null($courseCode)) {
  3349. api_set_firstpage_parameter($courseCode);
  3350. }
  3351. // If the user has no user ID, then his session has expired
  3352. $form = api_get_not_allowed_login_form();
  3353. // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (above)
  3354. $content = Display::return_message(get_lang('You are not allowed to see this page. Either your connection has expired or you are trying to access a page for which you do not have the sufficient privileges.'), 'error', false);
  3355. if (!empty($courseCode)) {
  3356. $content .= '<h4>'.get_lang('Please login to go to this course').'</h4>';
  3357. }
  3358. $content .= '<div class="well">';
  3359. $content .= $form->returnForm();
  3360. $content .= '</div>';
  3361. if (!empty($courseCode)) {
  3362. $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
  3363. get_lang('Return to Course Homepage').'</a></p>';
  3364. } else {
  3365. $content .= '<hr/><p style="text-align:center"><a href="'.$home_url.'">'.
  3366. get_lang('Back to Home Page.').'</a></p>';
  3367. }
  3368. $tpl->setLoginBodyClass();
  3369. $tpl->assign('content', $content);
  3370. $tpl->display_one_col_template();
  3371. exit;
  3372. }
  3373. if ($user_id != 0 && !api_is_anonymous()) {
  3374. $tpl->display_one_col_template();
  3375. exit;
  3376. }
  3377. $msg = null;
  3378. // The session is over and we were not in a course,
  3379. // or we try to get directly to a private course without being logged
  3380. $courseId = api_get_course_int_id();
  3381. if (!empty($courseId)) {
  3382. api_set_firstpage_parameter(api_get_course_id());
  3383. $tpl->setLoginBodyClass();
  3384. // see same text in auth/gotocourse.php and main_api.lib.php function api_not_allowed (bellow)
  3385. $msg = Display::return_message(get_lang('You are not allowed to see this page. Either your connection has expired or you are trying to access a page for which you do not have the sufficient privileges.'), 'error', false);
  3386. $msg .= '<h4>'.get_lang('Please login to go to this course').'</h4>';
  3387. $form = api_get_not_allowed_login_form();
  3388. $msg .= '<div class="well">';
  3389. $msg .= $form->returnForm();
  3390. $msg .= '</div>';
  3391. if ($casEnabled) {
  3392. $msg .= "</div>";
  3393. }
  3394. } else {
  3395. // we were not in a course, return to home page
  3396. $msg = Display::return_message(
  3397. get_lang('You are not allowed to see this page. Either your connection has expired or you are trying to access a page for which you do not have the sufficient privileges.'),
  3398. 'error',
  3399. false
  3400. );
  3401. $msg .= '<p class="text-center">
  3402. <a class="btn btn-default" href="'.$home_url.'">'.get_lang('Back to Home Page.').'</a>
  3403. </p>';
  3404. if (!empty($message)) {
  3405. $msg = $message;
  3406. }
  3407. if (api_is_anonymous()) {
  3408. $form = api_get_not_allowed_login_form();
  3409. $msg .= '<div class="well">';
  3410. $msg .= $form->returnForm();
  3411. $msg .= '</div>';
  3412. }
  3413. }
  3414. $tpl->assign('content', $msg);
  3415. $tpl->display_one_col_template();
  3416. exit;
  3417. }
  3418. /**
  3419. * @return FormValidator
  3420. */
  3421. function api_get_not_allowed_login_form()
  3422. {
  3423. $action = api_get_self().'?'.Security::remove_XSS($_SERVER['QUERY_STRING']);
  3424. $action = str_replace('&amp;', '&', $action);
  3425. Session::write('redirect_after_not_allow_page', $action);
  3426. $action .= '&redirect_after_not_allow_page=1';
  3427. $form = new FormValidator(
  3428. 'formLogin',
  3429. 'post',
  3430. $action,
  3431. null,
  3432. ['class' => 'form-stacked']
  3433. );
  3434. $params = [
  3435. 'placeholder' => get_lang('Username'),
  3436. 'class' => 'col-md-3',
  3437. ];
  3438. if (api_browser_support('autocapitalize')) {
  3439. $params['autocapitalize'] = 'none';
  3440. }
  3441. $form->addElement(
  3442. 'text',
  3443. 'login',
  3444. null,
  3445. $params
  3446. );
  3447. $form->addElement(
  3448. 'password',
  3449. 'password',
  3450. null,
  3451. ['placeholder' => get_lang('Password'), 'class' => 'col-md-3']
  3452. ); //new
  3453. $form->addButtonNext(get_lang('Login'), 'submitAuth');
  3454. return $form;
  3455. }
  3456. /**
  3457. * Gets a UNIX timestamp from a database (MySQL) datetime format string.
  3458. *
  3459. * @param $last_post_datetime standard output date in a sql query
  3460. *
  3461. * @return int timestamp
  3462. *
  3463. * @author Toon Van Hoecke <Toon.VanHoecke@UGent.be>
  3464. *
  3465. * @version October 2003
  3466. * @desc convert sql date to unix timestamp
  3467. */
  3468. function convert_sql_date($last_post_datetime)
  3469. {
  3470. list($last_post_date, $last_post_time) = explode(' ', $last_post_datetime);
  3471. list($year, $month, $day) = explode('-', $last_post_date);
  3472. list($hour, $min, $sec) = explode(':', $last_post_time);
  3473. return mktime((int) $hour, (int) $min, (int) $sec, (int) $month, (int) $day, (int) $year);
  3474. }
  3475. /**
  3476. * Gets item visibility from the item_property table.
  3477. *
  3478. * Getting the visibility is done by getting the last updated visibility entry,
  3479. * using the largest session ID found if session 0 and another was found (meaning
  3480. * the only one that is actually from the session, in case there are results from
  3481. * session 0 *AND* session n).
  3482. *
  3483. * @param array $_course Course properties array (result of api_get_course_info())
  3484. * @param string $tool Tool (learnpath, document, etc)
  3485. * @param int $id The item ID in the given tool
  3486. * @param int $session The session ID (optional)
  3487. * @param int $user_id
  3488. * @param string $type
  3489. * @param string $group_id
  3490. *
  3491. * @return int -1 on error, 0 if invisible, 1 if visible
  3492. */
  3493. function api_get_item_visibility(
  3494. $_course,
  3495. $tool,
  3496. $id,
  3497. $session = 0,
  3498. $user_id = null,
  3499. $type = null,
  3500. $group_id = null
  3501. ) {
  3502. if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) {
  3503. return -1;
  3504. }
  3505. $tool = Database::escape_string($tool);
  3506. $id = (int) $id;
  3507. $session = (int) $session;
  3508. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  3509. $course_id = (int) $_course['real_id'];
  3510. $userCondition = '';
  3511. if (!empty($user_id)) {
  3512. $user_id = (int) $user_id;
  3513. $userCondition = " AND to_user_id = $user_id ";
  3514. }
  3515. $typeCondition = '';
  3516. if (!empty($type)) {
  3517. $type = Database::escape_string($type);
  3518. $typeCondition = " AND lastedit_type = '$type' ";
  3519. }
  3520. $groupCondition = '';
  3521. if (!empty($group_id)) {
  3522. $group_id = (int) $group_id;
  3523. $groupCondition = " AND to_group_id = '$group_id' ";
  3524. }
  3525. $sql = "SELECT visibility
  3526. FROM $TABLE_ITEMPROPERTY
  3527. WHERE
  3528. c_id = $course_id AND
  3529. tool = '$tool' AND
  3530. ref = $id AND
  3531. (session_id = $session OR session_id = 0 OR session_id IS NULL)
  3532. $userCondition $typeCondition $groupCondition
  3533. ORDER BY session_id DESC, lastedit_date DESC
  3534. LIMIT 1";
  3535. $res = Database::query($sql);
  3536. if ($res === false || Database::num_rows($res) == 0) {
  3537. return -1;
  3538. }
  3539. $row = Database::fetch_array($res);
  3540. return (int) $row['visibility'];
  3541. }
  3542. /**
  3543. * Delete a row in the c_item_property table.
  3544. *
  3545. * @param array $courseInfo
  3546. * @param string $tool
  3547. * @param int $itemId
  3548. * @param int $userId
  3549. * @param int $groupId group.iid
  3550. * @param int $sessionId
  3551. *
  3552. * @return false|null
  3553. */
  3554. function api_item_property_delete(
  3555. $courseInfo,
  3556. $tool,
  3557. $itemId,
  3558. $userId,
  3559. $groupId = 0,
  3560. $sessionId = 0
  3561. ) {
  3562. if (empty($courseInfo)) {
  3563. return false;
  3564. }
  3565. $courseId = (int) $courseInfo['real_id'];
  3566. if (empty($courseId) || empty($tool) || empty($itemId)) {
  3567. return false;
  3568. }
  3569. $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
  3570. $tool = Database::escape_string($tool);
  3571. $itemId = intval($itemId);
  3572. $userId = intval($userId);
  3573. $groupId = intval($groupId);
  3574. $sessionId = intval($sessionId);
  3575. $groupCondition = " AND to_group_id = $groupId ";
  3576. if (empty($groupId)) {
  3577. $groupCondition = " AND (to_group_id is NULL OR to_group_id = 0) ";
  3578. }
  3579. $userCondition = " AND to_user_id = $userId ";
  3580. if (empty($userId)) {
  3581. $userCondition = " AND (to_user_id is NULL OR to_user_id = 0) ";
  3582. }
  3583. $sessionCondition = api_get_session_condition($sessionId, true, false, 'session_id');
  3584. $sql = "DELETE FROM $table
  3585. WHERE
  3586. c_id = $courseId AND
  3587. tool = '$tool' AND
  3588. ref = $itemId
  3589. $sessionCondition
  3590. $userCondition
  3591. $groupCondition
  3592. ";
  3593. Database::query($sql);
  3594. }
  3595. /**
  3596. * Updates or adds item properties to the Item_propetry table
  3597. * Tool and lastedit_type are language independant strings (langvars->get_lang!).
  3598. *
  3599. * @param array $_course array with course properties
  3600. * @param string $tool tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
  3601. * @param int $item_id id of the item itself, linked to key of every tool ('id', ...)
  3602. * @param string $last_edit_type add or update action
  3603. * (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
  3604. * (2) "delete"
  3605. * (3) "visible"
  3606. * (4) "invisible"
  3607. * @param int $user_id id of the editing/adding user
  3608. * @param array $groupInfo must include group.iid/group.od
  3609. * @param int $to_user_id id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
  3610. * @param string $start_visible 0000-00-00 00:00:00 format
  3611. * @param string $end_visible 0000-00-00 00:00:00 format
  3612. * @param int $session_id The session ID, if any, otherwise will default to 0
  3613. *
  3614. * @return bool false if update fails
  3615. *
  3616. * @author Toon Van Hoecke <Toon.VanHoecke@UGent.be>, Ghent University
  3617. *
  3618. * @version January 2005
  3619. * @desc update the item_properties table (if entry not exists, insert) of the course
  3620. */
  3621. function api_item_property_update(
  3622. $_course,
  3623. $tool,
  3624. $item_id,
  3625. $last_edit_type,
  3626. $user_id,
  3627. $groupInfo = [],
  3628. $to_user_id = null,
  3629. $start_visible = '',
  3630. $end_visible = '',
  3631. $session_id = 0
  3632. ) {
  3633. if (empty($_course)) {
  3634. return false;
  3635. }
  3636. $course_id = $_course['real_id'];
  3637. if (empty($course_id)) {
  3638. return false;
  3639. }
  3640. $to_group_id = 0;
  3641. if (!empty($groupInfo) && isset($groupInfo['iid'])) {
  3642. $to_group_id = (int) $groupInfo['iid'];
  3643. }
  3644. $em = Database::getManager();
  3645. // Definition of variables.
  3646. $tool = Database::escape_string($tool);
  3647. $item_id = (int) $item_id;
  3648. $lastEditTypeNoFilter = $last_edit_type;
  3649. $last_edit_type = Database::escape_string($last_edit_type);
  3650. $user_id = (int) $user_id;
  3651. $startVisible = "NULL";
  3652. if (!empty($start_visible)) {
  3653. $start_visible = Database::escape_string($start_visible);
  3654. $startVisible = "'$start_visible'";
  3655. }
  3656. $endVisible = "NULL";
  3657. if (!empty($end_visible)) {
  3658. $end_visible = Database::escape_string($end_visible);
  3659. $endVisible = "'$end_visible'";
  3660. }
  3661. $to_filter = '';
  3662. $time = api_get_utc_datetime();
  3663. if (!empty($session_id)) {
  3664. $session_id = (int) $session_id;
  3665. } else {
  3666. $session_id = api_get_session_id();
  3667. }
  3668. // Definition of tables.
  3669. $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
  3670. if ($to_user_id <= 0) {
  3671. $to_user_id = null; // No to_user_id set
  3672. }
  3673. if (!is_null($to_user_id)) {
  3674. // $to_user_id has more priority than $to_group_id
  3675. $to_user_id = (int) $to_user_id;
  3676. $to_field = 'to_user_id';
  3677. $to_value = $to_user_id;
  3678. } else {
  3679. // $to_user_id is not set.
  3680. $to_field = 'to_group_id';
  3681. $to_value = $to_group_id;
  3682. }
  3683. $toValueCondition = empty($to_value) ? 'NULL' : "'$to_value'";
  3684. // Set filters for $to_user_id and $to_group_id, with priority for $to_user_id
  3685. $condition_session = " AND session_id = $session_id ";
  3686. if (empty($session_id)) {
  3687. $condition_session = ' AND (session_id = 0 OR session_id IS NULL) ';
  3688. }
  3689. $filter = " c_id = $course_id AND tool = '$tool' AND ref = $item_id $condition_session ";
  3690. // Check whether $to_user_id and $to_group_id are passed in the function call.
  3691. // If both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
  3692. if (is_null($to_user_id) && is_null($to_group_id)) {
  3693. $to_group_id = 0;
  3694. }
  3695. if (!is_null($to_user_id)) {
  3696. // Set filter to intended user.
  3697. $to_filter = " AND to_user_id = $to_user_id $condition_session";
  3698. } else {
  3699. // Set filter to intended group.
  3700. if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
  3701. $to_filter = " AND to_group_id = $to_group_id $condition_session";
  3702. }
  3703. }
  3704. // Adding filter if set.
  3705. $filter .= $to_filter;
  3706. // Update if possible
  3707. $set_type = '';
  3708. switch ($lastEditTypeNoFilter) {
  3709. case 'delete':
  3710. // delete = make item only visible for the platform admin.
  3711. $visibility = '2';
  3712. if (!empty($session_id)) {
  3713. // Check whether session id already exist into item_properties for updating visibility or add it.
  3714. $sql = "SELECT session_id FROM $tableItemProperty
  3715. WHERE
  3716. c_id = $course_id AND
  3717. tool = '$tool' AND
  3718. ref = $item_id AND
  3719. session_id = $session_id";
  3720. $rs = Database::query($sql);
  3721. if (Database::num_rows($rs) > 0) {
  3722. $sql = "UPDATE $tableItemProperty
  3723. SET lastedit_type = '".str_replace('_', '', ucwords($tool))."Deleted',
  3724. lastedit_date = '$time',
  3725. lastedit_user_id = $user_id,
  3726. visibility = $visibility,
  3727. session_id = $session_id $set_type
  3728. WHERE $filter";
  3729. $result = Database::query($sql);
  3730. } else {
  3731. $sql = "INSERT INTO $tableItemProperty (c_id, tool, ref, insert_date, insert_user_id, lastedit_date, lastedit_type, lastedit_user_id, $to_field, visibility, start_visible, end_visible, session_id)
  3732. VALUES ($course_id, '$tool',$item_id, '$time', $user_id, '$time', '$last_edit_type',$user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
  3733. $result = Database::query($sql);
  3734. $id = Database::insert_id();
  3735. if ($id) {
  3736. $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
  3737. Database::query($sql);
  3738. }
  3739. }
  3740. } else {
  3741. $sql = "UPDATE $tableItemProperty
  3742. SET
  3743. lastedit_type='".str_replace('_', '', ucwords($tool))."Deleted',
  3744. lastedit_date='$time',
  3745. lastedit_user_id = $user_id,
  3746. visibility = $visibility $set_type
  3747. WHERE $filter";
  3748. $result = Database::query($sql);
  3749. }
  3750. break;
  3751. case 'visible': // Change item to visible.
  3752. $visibility = '1';
  3753. if (!empty($session_id)) {
  3754. // Check whether session id already exist into item_properties for updating visibility or add it.
  3755. $sql = "SELECT session_id FROM $tableItemProperty
  3756. WHERE
  3757. c_id = $course_id AND
  3758. tool = '$tool' AND
  3759. ref = $item_id AND
  3760. session_id = $session_id";
  3761. $rs = Database::query($sql);
  3762. if (Database::num_rows($rs) > 0) {
  3763. $sql = "UPDATE $tableItemProperty
  3764. SET
  3765. lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
  3766. lastedit_date='$time',
  3767. lastedit_user_id = $user_id,
  3768. visibility = $visibility,
  3769. session_id = $session_id $set_type
  3770. WHERE $filter";
  3771. $result = Database::query($sql);
  3772. } else {
  3773. $sql = "INSERT INTO $tableItemProperty (c_id, tool, ref, insert_date, insert_user_id, lastedit_date, lastedit_type, lastedit_user_id, $to_field, visibility, start_visible, end_visible, session_id)
  3774. VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
  3775. $result = Database::query($sql);
  3776. $id = Database::insert_id();
  3777. if ($id) {
  3778. $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
  3779. Database::query($sql);
  3780. }
  3781. }
  3782. } else {
  3783. $sql = "UPDATE $tableItemProperty
  3784. SET
  3785. lastedit_type='".str_replace('_', '', ucwords($tool))."Visible',
  3786. lastedit_date='$time',
  3787. lastedit_user_id = $user_id,
  3788. visibility = $visibility $set_type
  3789. WHERE $filter";
  3790. $result = Database::query($sql);
  3791. }
  3792. break;
  3793. case 'invisible': // Change item to invisible.
  3794. $visibility = '0';
  3795. if (!empty($session_id)) {
  3796. // Check whether session id already exist into item_properties for updating visibility or add it
  3797. $sql = "SELECT session_id FROM $tableItemProperty
  3798. WHERE
  3799. c_id = $course_id AND
  3800. tool = '$tool' AND
  3801. ref = $item_id AND
  3802. session_id = $session_id";
  3803. $rs = Database::query($sql);
  3804. if (Database::num_rows($rs) > 0) {
  3805. $sql = "UPDATE $tableItemProperty
  3806. SET
  3807. lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
  3808. lastedit_date = '$time',
  3809. lastedit_user_id = $user_id,
  3810. visibility = $visibility,
  3811. session_id = $session_id $set_type
  3812. WHERE $filter";
  3813. $result = Database::query($sql);
  3814. } else {
  3815. $sql = "INSERT INTO $tableItemProperty (c_id, tool, ref, insert_date, insert_user_id, lastedit_date, lastedit_type, lastedit_user_id,$to_field, visibility, start_visible, end_visible, session_id)
  3816. VALUES ($course_id, '$tool', $item_id, '$time', $user_id, '$time', '$last_edit_type', $user_id, $toValueCondition, $visibility, $startVisible, $endVisible, $session_id)";
  3817. $result = Database::query($sql);
  3818. $id = Database::insert_id();
  3819. if ($id) {
  3820. $sql = "UPDATE $tableItemProperty SET id = iid WHERE iid = $id";
  3821. Database::query($sql);
  3822. }
  3823. }
  3824. } else {
  3825. $sql = "UPDATE $tableItemProperty
  3826. SET
  3827. lastedit_type = '".str_replace('_', '', ucwords($tool))."Invisible',
  3828. lastedit_date = '$time',
  3829. lastedit_user_id = $user_id,
  3830. visibility = $visibility $set_type
  3831. WHERE $filter";
  3832. $result = Database::query($sql);
  3833. }
  3834. break;
  3835. default: // The item will be added or updated.
  3836. $set_type = ", lastedit_type = '$last_edit_type' ";
  3837. $visibility = '1';
  3838. //$filter .= $to_filter; already added
  3839. $sql = "UPDATE $tableItemProperty
  3840. SET
  3841. lastedit_date = '$time',
  3842. lastedit_user_id = $user_id $set_type
  3843. WHERE $filter";
  3844. $result = Database::query($sql);
  3845. }
  3846. // Insert if no entries are found (can only happen in case of $last_edit_type switch is 'default').
  3847. if ($result == false || Database::affected_rows($result) == 0) {
  3848. $objCourse = $em->find('ChamiloCoreBundle:Course', intval($course_id));
  3849. $objTime = new DateTime('now', new DateTimeZone('UTC'));
  3850. $objUser = api_get_user_entity($user_id);
  3851. if (empty($objUser)) {
  3852. // Use anonymous
  3853. $user_id = api_get_anonymous_id();
  3854. $objUser = api_get_user_entity($user_id);
  3855. }
  3856. $objGroup = null;
  3857. if (!empty($to_group_id)) {
  3858. $objGroup = $em->find('ChamiloCourseBundle:CGroupInfo', $to_group_id);
  3859. }
  3860. $objToUser = api_get_user_entity($to_user_id);
  3861. $objSession = $em->find('ChamiloCoreBundle:Session', intval($session_id));
  3862. $startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
  3863. $endVisibleDate = !empty($endVisibleDate) ? new DateTime($endVisibleDate, new DateTimeZone('UTC')) : null;
  3864. $cItemProperty = new CItemProperty($objCourse);
  3865. $cItemProperty
  3866. ->setTool($tool)
  3867. ->setRef($item_id)
  3868. ->setInsertDate($objTime)
  3869. ->setInsertUser($objUser)
  3870. ->setLasteditDate($objTime)
  3871. ->setLasteditType($last_edit_type)
  3872. ->setGroup($objGroup)
  3873. ->setToUser($objToUser)
  3874. ->setVisibility($visibility)
  3875. ->setStartVisible($startVisibleDate)
  3876. ->setEndVisible($endVisibleDate)
  3877. ->setSession($objSession);
  3878. $em->persist($cItemProperty);
  3879. $em->flush();
  3880. $id = $cItemProperty->getIid();
  3881. if ($id) {
  3882. $cItemProperty->setId($id);
  3883. $em->merge($cItemProperty);
  3884. $em->flush();
  3885. return false;
  3886. }
  3887. }
  3888. return true;
  3889. }
  3890. /**
  3891. * Gets item property by tool.
  3892. *
  3893. * @param string course code
  3894. * @param string tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
  3895. * @param int id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
  3896. * @param int $session_id
  3897. * @param string $tool
  3898. * @param string $course_code
  3899. *
  3900. * @return array All fields from c_item_property (all rows found) or empty array
  3901. */
  3902. function api_get_item_property_by_tool($tool, $course_code, $session_id = null)
  3903. {
  3904. $course_info = api_get_course_info($course_code);
  3905. $tool = Database::escape_string($tool);
  3906. // Definition of tables.
  3907. $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
  3908. $session_id = (int) $session_id;
  3909. $session_condition = ' AND session_id = '.$session_id;
  3910. if (empty($session_id)) {
  3911. $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
  3912. }
  3913. $course_id = $course_info['real_id'];
  3914. $sql = "SELECT * FROM $item_property_table
  3915. WHERE
  3916. c_id = $course_id AND
  3917. tool = '$tool'
  3918. $session_condition ";
  3919. $rs = Database::query($sql);
  3920. $list = [];
  3921. if (Database::num_rows($rs) > 0) {
  3922. while ($row = Database::fetch_array($rs, 'ASSOC')) {
  3923. $list[] = $row;
  3924. }
  3925. }
  3926. return $list;
  3927. }
  3928. /**
  3929. * Gets item property by tool and user.
  3930. *
  3931. * @param int $userId
  3932. * @param int $tool
  3933. * @param int $courseId
  3934. * @param int $session_id
  3935. *
  3936. * @return array
  3937. */
  3938. function api_get_item_property_list_by_tool_by_user(
  3939. $userId,
  3940. $tool,
  3941. $courseId,
  3942. $session_id = 0
  3943. ) {
  3944. $userId = intval($userId);
  3945. $tool = Database::escape_string($tool);
  3946. $session_id = intval($session_id);
  3947. $courseId = intval($courseId);
  3948. // Definition of tables.
  3949. $item_property_table = Database::get_course_table(TABLE_ITEM_PROPERTY);
  3950. $session_condition = ' AND session_id = '.$session_id;
  3951. if (empty($session_id)) {
  3952. $session_condition = " AND (session_id = 0 OR session_id IS NULL) ";
  3953. }
  3954. $sql = "SELECT * FROM $item_property_table
  3955. WHERE
  3956. insert_user_id = $userId AND
  3957. c_id = $courseId AND
  3958. tool = '$tool'
  3959. $session_condition ";
  3960. $rs = Database::query($sql);
  3961. $list = [];
  3962. if (Database::num_rows($rs) > 0) {
  3963. while ($row = Database::fetch_array($rs, 'ASSOC')) {
  3964. $list[] = $row;
  3965. }
  3966. }
  3967. return $list;
  3968. }
  3969. /**
  3970. * Gets item property id from tool of a course.
  3971. *
  3972. * @param string $course_code course code
  3973. * @param string $tool tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
  3974. * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
  3975. * @param int $sessionId Session ID (optional)
  3976. *
  3977. * @return int
  3978. */
  3979. function api_get_item_property_id($course_code, $tool, $ref, $sessionId = 0)
  3980. {
  3981. $course_info = api_get_course_info($course_code);
  3982. $tool = Database::escape_string($tool);
  3983. $ref = (int) $ref;
  3984. // Definition of tables.
  3985. $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
  3986. $course_id = $course_info['real_id'];
  3987. $sessionId = (int) $sessionId;
  3988. $sessionCondition = " AND session_id = $sessionId ";
  3989. if (empty($sessionId)) {
  3990. $sessionCondition = ' AND (session_id = 0 OR session_id IS NULL) ';
  3991. }
  3992. $sql = "SELECT id FROM $tableItemProperty
  3993. WHERE
  3994. c_id = $course_id AND
  3995. tool = '$tool' AND
  3996. ref = $ref
  3997. $sessionCondition";
  3998. $rs = Database::query($sql);
  3999. $item_property_id = '';
  4000. if (Database::num_rows($rs) > 0) {
  4001. $row = Database::fetch_array($rs);
  4002. $item_property_id = $row['id'];
  4003. }
  4004. return $item_property_id;
  4005. }
  4006. /**
  4007. * Inserts a record in the track_e_item_property table (No update).
  4008. *
  4009. * @param string $tool
  4010. * @param int $ref
  4011. * @param string $title
  4012. * @param string $content
  4013. * @param int $progress
  4014. *
  4015. * @return bool|int
  4016. */
  4017. function api_track_item_property_update($tool, $ref, $title, $content, $progress)
  4018. {
  4019. $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
  4020. $course_id = api_get_course_int_id(); //numeric
  4021. $course_code = api_get_course_id(); //alphanumeric
  4022. $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
  4023. if (!empty($item_property_id)) {
  4024. $sql = "INSERT IGNORE INTO $tbl_stats_item_property SET
  4025. course_id = '$course_id',
  4026. item_property_id = '$item_property_id',
  4027. title = '".Database::escape_string($title)."',
  4028. content = '".Database::escape_string($content)."',
  4029. progress = '".intval($progress)."',
  4030. lastedit_date = '".api_get_utc_datetime()."',
  4031. lastedit_user_id = '".api_get_user_id()."',
  4032. session_id = '".api_get_session_id()."'";
  4033. $result = Database::query($sql);
  4034. $affected_rows = Database::affected_rows($result);
  4035. return $affected_rows;
  4036. }
  4037. return false;
  4038. }
  4039. /**
  4040. * @param string $tool
  4041. * @param int $ref
  4042. *
  4043. * @return array|resource
  4044. */
  4045. function api_get_track_item_property_history($tool, $ref)
  4046. {
  4047. $tbl_stats_item_property = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY);
  4048. $course_id = api_get_course_int_id(); //numeric
  4049. $course_code = api_get_course_id(); //alphanumeric
  4050. $item_property_id = api_get_item_property_id($course_code, $tool, $ref);
  4051. $sql = "SELECT * FROM $tbl_stats_item_property
  4052. WHERE item_property_id = $item_property_id AND course_id = $course_id
  4053. ORDER BY lastedit_date DESC";
  4054. $result = Database::query($sql);
  4055. if ($result === false or $result === null) {
  4056. $result = [];
  4057. } else {
  4058. $result = Database::store_result($result, 'ASSOC');
  4059. }
  4060. return $result;
  4061. }
  4062. /**
  4063. * Gets item property data from tool of a course id.
  4064. *
  4065. * @param int $course_id
  4066. * @param string $tool tool name, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
  4067. * @param int $ref id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
  4068. * @param int $session_id
  4069. * @param int $groupId
  4070. *
  4071. * @return array with all fields from c_item_property, empty array if not found or false if course could not be found
  4072. */
  4073. function api_get_item_property_info($course_id, $tool, $ref, $session_id = 0, $groupId = 0)
  4074. {
  4075. $courseInfo = api_get_course_info_by_id($course_id);
  4076. if (empty($courseInfo)) {
  4077. return false;
  4078. }
  4079. $tool = Database::escape_string($tool);
  4080. $course_id = $courseInfo['real_id'];
  4081. $ref = (int) $ref;
  4082. $session_id = (int) $session_id;
  4083. $sessionCondition = " session_id = $session_id";
  4084. if (empty($session_id)) {
  4085. $sessionCondition = ' (session_id = 0 OR session_id IS NULL) ';
  4086. }
  4087. // Definition of tables.
  4088. $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
  4089. $sql = "SELECT * FROM $table
  4090. WHERE
  4091. c_id = $course_id AND
  4092. tool = '$tool' AND
  4093. ref = $ref AND
  4094. $sessionCondition ";
  4095. if (!empty($groupId)) {
  4096. $groupId = (int) $groupId;
  4097. $sql .= " AND to_group_id = $groupId ";
  4098. }
  4099. $rs = Database::query($sql);
  4100. $row = [];
  4101. if (Database::num_rows($rs) > 0) {
  4102. $row = Database::fetch_array($rs, 'ASSOC');
  4103. }
  4104. return $row;
  4105. }
  4106. /**
  4107. * Displays a combo box so the user can select his/her preferred language.
  4108. *
  4109. * @param string The desired name= value for the select
  4110. * @param bool Whether we use the JQuery Chozen library or not
  4111. * (in some cases, like the indexing language picker, it can alter the presentation)
  4112. *
  4113. * @deprecated
  4114. *
  4115. * @return string
  4116. */
  4117. function api_get_languages_combo($name = 'language')
  4118. {
  4119. $ret = '';
  4120. $platformLanguage = api_get_setting('platformLanguage');
  4121. // Retrieve a complete list of all the languages.
  4122. $language_list = api_get_languages();
  4123. if (count($language_list) < 2) {
  4124. return $ret;
  4125. }
  4126. // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
  4127. if (isset($_SESSION['user_language_choice'])) {
  4128. $default = $_SESSION['user_language_choice'];
  4129. } else {
  4130. $default = $platformLanguage;
  4131. }
  4132. $ret .= '<select name="'.$name.'" id="language_chosen" class="selectpicker show-tick form-control">';
  4133. foreach ($language_list as $key => $value) {
  4134. if ($key == $default) {
  4135. $selected = ' selected="selected"';
  4136. } else {
  4137. $selected = '';
  4138. }
  4139. $ret .= sprintf('<option value=%s" %s>%s</option>', $key, $selected, $value);
  4140. }
  4141. $ret .= '</select>';
  4142. return $ret;
  4143. }
  4144. /**
  4145. * Displays a form (drop down menu) so the user can select his/her preferred language.
  4146. * The form works with or without javascript.
  4147. *
  4148. * @param bool Hide form if only one language available (defaults to false = show the box anyway)
  4149. * @param bool $showAsButton
  4150. *
  4151. * @return string|null Display the box directly
  4152. */
  4153. function api_display_language_form($hide_if_no_choice = false, $showAsButton = false)
  4154. {
  4155. // Retrieve a complete list of all the languages.
  4156. $language_list = api_get_languages();
  4157. if (count($language_list['name']) <= 1 && $hide_if_no_choice) {
  4158. return; //don't show any form
  4159. }
  4160. // The the current language of the user so that his/her language occurs as selected in the dropdown menu.
  4161. if (isset($_SESSION['user_language_choice'])) {
  4162. $user_selected_language = $_SESSION['user_language_choice'];
  4163. }
  4164. if (empty($user_selected_language)) {
  4165. $user_selected_language = api_get_setting('platformLanguage');
  4166. }
  4167. $currentLanguageId = api_get_language_id($user_selected_language);
  4168. $currentLanguageInfo = api_get_language_info($currentLanguageId);
  4169. $countryCode = languageToCountryIsoCode($currentLanguageInfo['isocode']);
  4170. $url = api_get_self();
  4171. if ($showAsButton) {
  4172. $html = '<div class="btn-group">
  4173. <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
  4174. <span class="flag-icon flag-icon-'.$countryCode.'"></span>
  4175. '.$currentLanguageInfo['original_name'].'
  4176. <span class="caret">
  4177. </span>
  4178. </button>';
  4179. } else {
  4180. $html = '
  4181. <a href="'.$url.'" class="dropdown-toggle" data-toggle="dropdown" role="button">
  4182. <span class="flag-icon flag-icon-'.$countryCode.'"></span>
  4183. '.$currentLanguageInfo['original_name'].'
  4184. <span class="caret"></span>
  4185. </a>
  4186. ';
  4187. }
  4188. $html .= '<ul class="dropdown-menu" role="menu">';
  4189. foreach ($language_list['all'] as $key => $data) {
  4190. $urlLink = $url.'?language='.$data['english_name'];
  4191. $html .= '<li><a href="'.$urlLink.'"><span class="flag-icon flag-icon-'.languageToCountryIsoCode($data['isocode']).'"></span> '.$data['original_name'].'</a></li>';
  4192. }
  4193. $html .= '</ul>';
  4194. if ($showAsButton) {
  4195. $html .= '</div>';
  4196. }
  4197. return $html;
  4198. }
  4199. /**
  4200. * @param string $languageIsoCode
  4201. *
  4202. * @return string
  4203. */
  4204. function languageToCountryIsoCode($languageIsoCode)
  4205. {
  4206. $allow = api_get_configuration_value('language_flags_by_country');
  4207. // @todo save in DB
  4208. switch ($languageIsoCode) {
  4209. case 'ko':
  4210. $country = 'kr';
  4211. break;
  4212. case 'ja':
  4213. $country = 'jp';
  4214. break;
  4215. case 'ca':
  4216. $country = 'es';
  4217. if ($allow) {
  4218. $country = 'catalan';
  4219. }
  4220. break;
  4221. case 'gl': // galego
  4222. $country = 'es';
  4223. if ($allow) {
  4224. $country = 'galician';
  4225. }
  4226. break;
  4227. case 'ka':
  4228. $country = 'ge';
  4229. break;
  4230. case 'sl':
  4231. $country = 'si';
  4232. break;
  4233. case 'eu': // Euskera
  4234. $country = 'es';
  4235. if ($allow) {
  4236. $country = 'basque';
  4237. }
  4238. break;
  4239. case 'cs':
  4240. $country = 'cz';
  4241. break;
  4242. case 'el':
  4243. $country = 'ae';
  4244. break;
  4245. case 'ar':
  4246. $country = 'ae';
  4247. break;
  4248. case 'en_US':
  4249. case 'en':
  4250. $country = 'gb';
  4251. break;
  4252. case 'he':
  4253. $country = 'il';
  4254. break;
  4255. case 'uk': // Ukraine
  4256. $country = 'ua';
  4257. break;
  4258. case 'da':
  4259. $country = 'dk';
  4260. break;
  4261. case 'pt-BR':
  4262. $country = 'br';
  4263. break;
  4264. case 'qu':
  4265. $country = 'pe';
  4266. break;
  4267. case 'sv':
  4268. $country = 'se';
  4269. break;
  4270. case 'zh-TW':
  4271. case 'zh':
  4272. $country = 'cn';
  4273. break;
  4274. default:
  4275. $country = $languageIsoCode;
  4276. break;
  4277. }
  4278. $country = strtolower($country);
  4279. return $country;
  4280. }
  4281. /**
  4282. * Returns a list of all the languages that are made available by the admin.
  4283. *
  4284. * @return array An array with all languages. Structure of the array is
  4285. * array['name'] = An array with the name of every language
  4286. * array['folder'] = An array with the corresponding names of the language-folders in the filesystem
  4287. */
  4288. function api_get_languages()
  4289. {
  4290. $table = Database::get_main_table(TABLE_MAIN_LANGUAGE);
  4291. $sql = "SELECT * FROM $table WHERE available='1'
  4292. ORDER BY original_name ASC";
  4293. $result = Database::query($sql);
  4294. $languages = [];
  4295. while ($row = Database::fetch_array($result, 'ASSOC')) {
  4296. $languages[$row['isocode']] = $row['original_name'];
  4297. }
  4298. return $languages;
  4299. }
  4300. /**
  4301. * Returns a list of all the languages that are made available by the admin.
  4302. *
  4303. * @return array
  4304. */
  4305. function api_get_languages_to_array()
  4306. {
  4307. $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
  4308. $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
  4309. $result = Database::query($sql);
  4310. $languages = [];
  4311. while ($row = Database::fetch_array($result)) {
  4312. $languages[$row['dokeos_folder']] = $row['original_name'];
  4313. }
  4314. return $languages;
  4315. }
  4316. /**
  4317. * Returns the id (the database id) of a language.
  4318. *
  4319. * @param string language name (the corresponding name of the language-folder in the filesystem)
  4320. *
  4321. * @return int id of the language
  4322. */
  4323. function api_get_language_id($language)
  4324. {
  4325. $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
  4326. if (empty($language)) {
  4327. return null;
  4328. }
  4329. $language = Database::escape_string($language);
  4330. $sql = "SELECT id FROM $tbl_language
  4331. WHERE dokeos_folder = '$language' LIMIT 1";
  4332. $result = Database::query($sql);
  4333. $row = Database::fetch_array($result);
  4334. return $row['id'];
  4335. }
  4336. /**
  4337. * Get the language information by its id.
  4338. *
  4339. * @param int $languageId
  4340. *
  4341. * @throws Exception
  4342. *
  4343. * @return array
  4344. */
  4345. function api_get_language_info($languageId)
  4346. {
  4347. if (empty($languageId)) {
  4348. return [];
  4349. }
  4350. $language = Database::getManager()
  4351. ->find('ChamiloCoreBundle:Language', $languageId);
  4352. if (!$language) {
  4353. return [];
  4354. }
  4355. return [
  4356. 'id' => $language->getId(),
  4357. 'original_name' => $language->getOriginalName(),
  4358. 'english_name' => $language->getEnglishName(),
  4359. 'isocode' => $language->getIsocode(),
  4360. 'dokeos_folder' => $language->getDokeosFolder(),
  4361. 'available' => $language->getAvailable(),
  4362. 'parent_id' => $language->getParent() ? $language->getParent()->getId() : null,
  4363. ];
  4364. }
  4365. /**
  4366. * @param string $code
  4367. *
  4368. * @return \Chamilo\CoreBundle\Entity\Language
  4369. */
  4370. function api_get_language_from_iso($code)
  4371. {
  4372. $em = Database::getManager();
  4373. $language = $em->getRepository('ChamiloCoreBundle:Language')->findOneBy(['isocode' => $code]);
  4374. return $language;
  4375. }
  4376. /**
  4377. * Returns the name of the visual (CSS) theme to be applied on the current page.
  4378. * The returned name depends on the platform, course or user -wide settings.
  4379. *
  4380. * @return string The visual theme's name, it is the name of a folder inside web/css/themes
  4381. */
  4382. function api_get_visual_theme()
  4383. {
  4384. static $visual_theme;
  4385. if (!isset($visual_theme)) {
  4386. // Get style directly from DB
  4387. $styleFromDatabase = api_get_settings_params_simple(
  4388. [
  4389. 'variable = ? AND access_url = ?' => [
  4390. 'stylesheets',
  4391. api_get_current_access_url_id(),
  4392. ],
  4393. ]
  4394. );
  4395. if ($styleFromDatabase) {
  4396. $platform_theme = $styleFromDatabase['selected_value'];
  4397. } else {
  4398. $platform_theme = api_get_setting('stylesheets');
  4399. }
  4400. // Platform's theme.
  4401. $visual_theme = $platform_theme;
  4402. if (api_get_setting('user_selected_theme') == 'true') {
  4403. $user_info = api_get_user_info();
  4404. if (isset($user_info['theme'])) {
  4405. $user_theme = $user_info['theme'];
  4406. if (!empty($user_theme)) {
  4407. $visual_theme = $user_theme;
  4408. // User's theme.
  4409. }
  4410. }
  4411. }
  4412. $course_id = api_get_course_id();
  4413. if (!empty($course_id)) {
  4414. if (api_get_setting('allow_course_theme') == 'true') {
  4415. $course_theme = api_get_course_setting('course_theme', $course_id);
  4416. if (!empty($course_theme) && $course_theme != -1) {
  4417. if (!empty($course_theme)) {
  4418. // Course's theme.
  4419. $visual_theme = $course_theme;
  4420. }
  4421. }
  4422. $allow_lp_theme = api_get_course_setting('allow_learning_path_theme');
  4423. if ($allow_lp_theme == 1) {
  4424. global $lp_theme_css, $lp_theme_config;
  4425. // These variables come from the file lp_controller.php.
  4426. if (!$lp_theme_config) {
  4427. if (!empty($lp_theme_css)) {
  4428. // LP's theme.
  4429. $visual_theme = $lp_theme_css;
  4430. }
  4431. }
  4432. }
  4433. }
  4434. }
  4435. if (empty($visual_theme)) {
  4436. $visual_theme = 'chamilo';
  4437. }
  4438. global $lp_theme_log;
  4439. if ($lp_theme_log) {
  4440. $visual_theme = $platform_theme;
  4441. }
  4442. }
  4443. return $visual_theme;
  4444. }
  4445. /**
  4446. * Returns a list of CSS themes currently available in the CSS folder
  4447. * The folder must have a default.css file.
  4448. *
  4449. * @param bool $getOnlyThemeFromVirtualInstance Used by the vchamilo plugin
  4450. *
  4451. * @return array list of themes directories from the css folder
  4452. * Note: Directory names (names of themes) in the file system should contain ASCII-characters only
  4453. */
  4454. function api_get_themes($getOnlyThemeFromVirtualInstance = false)
  4455. {
  4456. // This configuration value is set by the vchamilo plugin
  4457. $virtualTheme = api_get_configuration_value('virtual_css_theme_folder');
  4458. $readCssFolder = function ($dir) use ($virtualTheme) {
  4459. $finder = new Finder();
  4460. $themes = $finder->directories()->in($dir)->depth(0)->sortByName();
  4461. $list = [];
  4462. /** @var Symfony\Component\Finder\SplFileInfo $theme */
  4463. foreach ($themes as $theme) {
  4464. $folder = $theme->getFilename();
  4465. // A theme folder is consider if there's a default.css file
  4466. if (!file_exists($theme->getPathname().'/default.css')) {
  4467. continue;
  4468. }
  4469. $name = ucwords(str_replace('_', ' ', $folder));
  4470. if ($folder == $virtualTheme) {
  4471. continue;
  4472. }
  4473. $list[$folder] = $name;
  4474. }
  4475. return $list;
  4476. };
  4477. $dir = api_get_path(SYS_CSS_PATH).'themes/';
  4478. $list = $readCssFolder($dir);
  4479. if (!empty($virtualTheme)) {
  4480. $newList = $readCssFolder($dir.'/'.$virtualTheme);
  4481. if ($getOnlyThemeFromVirtualInstance) {
  4482. return $newList;
  4483. }
  4484. $list = $list + $newList;
  4485. asort($list);
  4486. }
  4487. return $list;
  4488. }
  4489. /**
  4490. * Find the largest sort value in a given user_course_category
  4491. * This function is used when we are moving a course to a different category
  4492. * and also when a user subscribes to courses (the new course is added at the end of the main category.
  4493. *
  4494. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  4495. *
  4496. * @param int $user_course_category the id of the user_course_category
  4497. * @param int $user_id
  4498. *
  4499. * @return int the value of the highest sort of the user_course_category
  4500. */
  4501. function api_max_sort_value($user_course_category, $user_id)
  4502. {
  4503. $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  4504. $sql = "SELECT max(sort) as max_sort FROM $tbl_course_user
  4505. WHERE
  4506. user_id='".intval($user_id)."' AND
  4507. relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
  4508. user_course_cat='".intval($user_course_category)."'";
  4509. $result_max = Database::query($sql);
  4510. if (Database::num_rows($result_max) == 1) {
  4511. $row_max = Database::fetch_array($result_max);
  4512. return $row_max['max_sort'];
  4513. }
  4514. return 0;
  4515. }
  4516. /**
  4517. * Transforms a number of seconds in hh:mm:ss format.
  4518. *
  4519. * @author Julian Prud'homme
  4520. *
  4521. * @param int $seconds number of seconds
  4522. * @param string $space
  4523. * @param bool $showSeconds
  4524. * @param bool $roundMinutes
  4525. *
  4526. * @return string the formatted time
  4527. */
  4528. function api_time_to_hms($seconds, $space = ':', $showSeconds = true, $roundMinutes = false)
  4529. {
  4530. // $seconds = -1 means that we have wrong data in the db.
  4531. if ($seconds == -1) {
  4532. return
  4533. get_lang('Unknown').
  4534. Display::return_icon(
  4535. 'info2.gif',
  4536. get_lang('The datas about this user were registered when the calculation of time spent on the platform wasn\'t possible.'),
  4537. ['align' => 'absmiddle', 'hspace' => '3px']
  4538. );
  4539. }
  4540. // How many hours ?
  4541. $hours = floor($seconds / 3600);
  4542. // How many minutes ?
  4543. $min = floor(($seconds - ($hours * 3600)) / 60);
  4544. if ($roundMinutes) {
  4545. if ($min >= 45) {
  4546. $min = 45;
  4547. }
  4548. if ($min >= 30 && $min <= 44) {
  4549. $min = 30;
  4550. }
  4551. if ($min >= 15 && $min <= 29) {
  4552. $min = 15;
  4553. }
  4554. if ($min >= 0 && $min <= 14) {
  4555. $min = 0;
  4556. }
  4557. }
  4558. // How many seconds
  4559. $sec = floor($seconds - ($hours * 3600) - ($min * 60));
  4560. if ($hours < 10) {
  4561. $hours = "0$hours";
  4562. }
  4563. if ($sec < 10) {
  4564. $sec = "0$sec";
  4565. }
  4566. if ($min < 10) {
  4567. $min = "0$min";
  4568. }
  4569. $seconds = '';
  4570. if ($showSeconds) {
  4571. $seconds = $space.$sec;
  4572. }
  4573. return $hours.$space.$min.$seconds;
  4574. }
  4575. /* FILE SYSTEM RELATED FUNCTIONS */
  4576. /**
  4577. * Returns the permissions to be assigned to every newly created directory by the web-server.
  4578. * The return value is based on the platform administrator's setting
  4579. * "Administration > Configuration settings > Security > Permissions for new directories".
  4580. *
  4581. * @return int returns the permissions in the format "Owner-Group-Others, Read-Write-Execute", as an integer value
  4582. */
  4583. function api_get_permissions_for_new_directories()
  4584. {
  4585. static $permissions;
  4586. if (!isset($permissions)) {
  4587. $permissions = trim(api_get_setting('permissions_for_new_directories'));
  4588. // The default value 0777 is according to that in the platform administration panel after fresh system installation.
  4589. $permissions = octdec(!empty($permissions) ? $permissions : '0777');
  4590. }
  4591. return $permissions;
  4592. }
  4593. /**
  4594. * Returns the permissions to be assigned to every newly created directory by the web-server.
  4595. * The return value is based on the platform administrator's setting
  4596. * "Administration > Configuration settings > Security > Permissions for new files".
  4597. *
  4598. * @return int returns the permissions in the format
  4599. * "Owner-Group-Others, Read-Write-Execute", as an integer value
  4600. */
  4601. function api_get_permissions_for_new_files()
  4602. {
  4603. static $permissions;
  4604. if (!isset($permissions)) {
  4605. $permissions = trim(api_get_setting('permissions_for_new_files'));
  4606. // The default value 0666 is according to that in the platform
  4607. // administration panel after fresh system installation.
  4608. $permissions = octdec(!empty($permissions) ? $permissions : '0666');
  4609. }
  4610. return $permissions;
  4611. }
  4612. /**
  4613. * Deletes a file, or a folder and its contents.
  4614. *
  4615. * @author Aidan Lister <aidan@php.net>
  4616. *
  4617. * @version 1.0.3
  4618. *
  4619. * @param string $dirname Directory to delete
  4620. * @param bool Deletes only the content or not
  4621. * @param bool $strict if one folder/file fails stop the loop
  4622. *
  4623. * @return bool Returns TRUE on success, FALSE on failure
  4624. *
  4625. * @see http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
  4626. *
  4627. * @author Yannick Warnier, adaptation for the Chamilo LMS, April, 2008
  4628. * @author Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
  4629. */
  4630. function rmdirr($dirname, $delete_only_content_in_folder = false, $strict = false)
  4631. {
  4632. $res = true;
  4633. // A sanity check.
  4634. if (!file_exists($dirname)) {
  4635. return false;
  4636. }
  4637. $php_errormsg = '';
  4638. // Simple delete for a file.
  4639. if (is_file($dirname) || is_link($dirname)) {
  4640. $res = unlink($dirname);
  4641. if ($res === false) {
  4642. error_log(__FILE__.' line '.__LINE__.': '.((bool) ini_get('track_errors') ? $php_errormsg : 'Error not recorded because track_errors is off in your php.ini'), 0);
  4643. }
  4644. return $res;
  4645. }
  4646. // Loop through the folder.
  4647. $dir = dir($dirname);
  4648. // A sanity check.
  4649. $is_object_dir = is_object($dir);
  4650. if ($is_object_dir) {
  4651. while (false !== $entry = $dir->read()) {
  4652. // Skip pointers.
  4653. if ($entry == '.' || $entry == '..') {
  4654. continue;
  4655. }
  4656. // Recurse.
  4657. if ($strict) {
  4658. $result = rmdirr("$dirname/$entry");
  4659. if ($result == false) {
  4660. $res = false;
  4661. break;
  4662. }
  4663. } else {
  4664. rmdirr("$dirname/$entry");
  4665. }
  4666. }
  4667. }
  4668. // Clean up.
  4669. if ($is_object_dir) {
  4670. $dir->close();
  4671. }
  4672. if ($delete_only_content_in_folder == false) {
  4673. $res = rmdir($dirname);
  4674. if ($res === false) {
  4675. error_log(__FILE__.' line '.__LINE__.': '.((bool) ini_get('track_errors') ? $php_errormsg : 'error not recorded because track_errors is off in your php.ini'), 0);
  4676. }
  4677. }
  4678. return $res;
  4679. }
  4680. // TODO: This function is to be simplified. File access modes to be implemented.
  4681. /**
  4682. * function adapted from a php.net comment
  4683. * copy recursively a folder.
  4684. *
  4685. * @param the source folder
  4686. * @param the dest folder
  4687. * @param an array of excluded file_name (without extension)
  4688. * @param copied_files the returned array of copied files
  4689. * @param string $source
  4690. * @param string $dest
  4691. */
  4692. function copyr($source, $dest, $exclude = [], $copied_files = [])
  4693. {
  4694. if (empty($dest)) {
  4695. return false;
  4696. }
  4697. // Simple copy for a file
  4698. if (is_file($source)) {
  4699. $path_info = pathinfo($source);
  4700. if (!in_array($path_info['filename'], $exclude)) {
  4701. copy($source, $dest);
  4702. }
  4703. return true;
  4704. } elseif (!is_dir($source)) {
  4705. //then source is not a dir nor a file, return
  4706. return false;
  4707. }
  4708. // Make destination directory.
  4709. if (!is_dir($dest)) {
  4710. mkdir($dest, api_get_permissions_for_new_directories());
  4711. }
  4712. // Loop through the folder.
  4713. $dir = dir($source);
  4714. while (false !== $entry = $dir->read()) {
  4715. // Skip pointers
  4716. if ($entry == '.' || $entry == '..') {
  4717. continue;
  4718. }
  4719. // Deep copy directories.
  4720. if ($dest !== "$source/$entry") {
  4721. $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
  4722. }
  4723. }
  4724. // Clean up.
  4725. $dir->close();
  4726. return true;
  4727. }
  4728. /**
  4729. * @todo: Using DIRECTORY_SEPARATOR is not recommended, this is an obsolete approach.
  4730. * Documentation header to be added here.
  4731. *
  4732. * @param string $pathname
  4733. * @param string $base_path_document
  4734. * @param int $session_id
  4735. *
  4736. * @return mixed True if directory already exists, false if a file already exists at
  4737. * the destination and null if everything goes according to plan
  4738. */
  4739. function copy_folder_course_session(
  4740. $pathname,
  4741. $base_path_document,
  4742. $session_id,
  4743. $course_info,
  4744. $document,
  4745. $source_course_id
  4746. ) {
  4747. $table = Database::get_course_table(TABLE_DOCUMENT);
  4748. $session_id = intval($session_id);
  4749. $source_course_id = intval($source_course_id);
  4750. // Check whether directory already exists.
  4751. if (is_dir($pathname) || empty($pathname)) {
  4752. return true;
  4753. }
  4754. // Ensure that a file with the same name does not already exist.
  4755. if (is_file($pathname)) {
  4756. trigger_error('copy_folder_course_session(): File exists', E_USER_WARNING);
  4757. return false;
  4758. }
  4759. $course_id = $course_info['real_id'];
  4760. $folders = explode(DIRECTORY_SEPARATOR, str_replace($base_path_document.DIRECTORY_SEPARATOR, '', $pathname));
  4761. $new_pathname = $base_path_document;
  4762. $path = '';
  4763. foreach ($folders as $folder) {
  4764. $new_pathname .= DIRECTORY_SEPARATOR.$folder;
  4765. $path .= DIRECTORY_SEPARATOR.$folder;
  4766. if (!file_exists($new_pathname)) {
  4767. $path = Database::escape_string($path);
  4768. $sql = "SELECT * FROM $table
  4769. WHERE
  4770. c_id = $source_course_id AND
  4771. path = '$path' AND
  4772. filetype = 'folder' AND
  4773. session_id = '$session_id'";
  4774. $rs1 = Database::query($sql);
  4775. $num_rows = Database::num_rows($rs1);
  4776. if ($num_rows == 0) {
  4777. mkdir($new_pathname, api_get_permissions_for_new_directories());
  4778. // Insert new folder with destination session_id.
  4779. $params = [
  4780. 'c_id' => $course_id,
  4781. 'path' => $path,
  4782. 'comment' => $document->comment,
  4783. 'title' => basename($new_pathname),
  4784. 'filetype' => 'folder',
  4785. 'size' => '0',
  4786. 'session_id' => $session_id,
  4787. ];
  4788. $document_id = Database::insert($table, $params);
  4789. if ($document_id) {
  4790. $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
  4791. Database::query($sql);
  4792. api_item_property_update(
  4793. $course_info,
  4794. TOOL_DOCUMENT,
  4795. $document_id,
  4796. 'FolderCreated',
  4797. api_get_user_id(),
  4798. 0,
  4799. 0,
  4800. null,
  4801. null,
  4802. $session_id
  4803. );
  4804. }
  4805. }
  4806. }
  4807. } // en foreach
  4808. }
  4809. // TODO: chmodr() is a better name. Some corrections are needed. Documentation header to be added here.
  4810. /**
  4811. * @param string $path
  4812. */
  4813. function api_chmod_R($path, $filemode)
  4814. {
  4815. if (!is_dir($path)) {
  4816. return chmod($path, $filemode);
  4817. }
  4818. $handler = opendir($path);
  4819. while ($file = readdir($handler)) {
  4820. if ($file != '.' && $file != '..') {
  4821. $fullpath = "$path/$file";
  4822. if (!is_dir($fullpath)) {
  4823. if (!chmod($fullpath, $filemode)) {
  4824. return false;
  4825. }
  4826. } else {
  4827. if (!api_chmod_R($fullpath, $filemode)) {
  4828. return false;
  4829. }
  4830. }
  4831. }
  4832. }
  4833. closedir($handler);
  4834. return chmod($path, $filemode);
  4835. }
  4836. // TODO: Where the following function has been copy/pased from? There is no information about author and license. Style, coding conventions...
  4837. /**
  4838. * Parse info file format. (e.g: file.info).
  4839. *
  4840. * Files should use an ini-like format to specify values.
  4841. * White-space generally doesn't matter, except inside values.
  4842. * e.g.
  4843. *
  4844. * @verbatim
  4845. * key = value
  4846. * key = "value"
  4847. * key = 'value'
  4848. * key = "multi-line
  4849. *
  4850. * value"
  4851. * key = 'multi-line
  4852. *
  4853. * value'
  4854. * key
  4855. * =
  4856. * 'value'
  4857. * @endverbatim
  4858. *
  4859. * Arrays are created using a GET-like syntax:
  4860. *
  4861. * @verbatim
  4862. * key[] = "numeric array"
  4863. * key[index] = "associative array"
  4864. * key[index][] = "nested numeric array"
  4865. * key[index][index] = "nested associative array"
  4866. * @endverbatim
  4867. *
  4868. * PHP constants are substituted in, but only when used as the entire value:
  4869. *
  4870. * Comments should start with a semi-colon at the beginning of a line.
  4871. *
  4872. * This function is NOT for placing arbitrary module-specific settings. Use
  4873. * variable_get() and variable_set() for that.
  4874. *
  4875. * Information stored in the module.info file:
  4876. * - name: The real name of the module for display purposes.
  4877. * - description: A brief description of the module.
  4878. * - dependencies: An array of shortnames of other modules this module depends on.
  4879. * - package: The name of the package of modules this module belongs to.
  4880. *
  4881. * Example of .info file:
  4882. * <code>
  4883. * @verbatim
  4884. * name = Forum
  4885. * description = Enables threaded discussions about general topics.
  4886. * dependencies[] = taxonomy
  4887. * dependencies[] = comment
  4888. * package = Core - optional
  4889. * version = VERSION
  4890. * @endverbatim
  4891. * </code>
  4892. *
  4893. * @param string $filename
  4894. * The file we are parsing. Accepts file with relative or absolute path.
  4895. *
  4896. * @return
  4897. * The info array
  4898. */
  4899. function api_parse_info_file($filename)
  4900. {
  4901. $info = [];
  4902. if (!file_exists($filename)) {
  4903. return $info;
  4904. }
  4905. $data = file_get_contents($filename);
  4906. if (preg_match_all('
  4907. @^\s* # Start at the beginning of a line, ignoring leading whitespace
  4908. ((?:
  4909. [^=;\[\]]| # Key names cannot contain equal signs, semi-colons or square brackets,
  4910. \[[^\[\]]*\] # unless they are balanced and not nested
  4911. )+?)
  4912. \s*=\s* # Key/value pairs are separated by equal signs (ignoring white-space)
  4913. (?:
  4914. ("(?:[^"]|(?<=\\\\)")*")| # Double-quoted string, which may contain slash-escaped quotes/slashes
  4915. (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
  4916. ([^\r\n]*?) # Non-quoted string
  4917. )\s*$ # Stop at the next end of a line, ignoring trailing whitespace
  4918. @msx', $data, $matches, PREG_SET_ORDER)) {
  4919. $key = $value1 = $value2 = $value3 = '';
  4920. foreach ($matches as $match) {
  4921. // Fetch the key and value string.
  4922. $i = 0;
  4923. foreach (['key', 'value1', 'value2', 'value3'] as $var) {
  4924. $$var = isset($match[++$i]) ? $match[$i] : '';
  4925. }
  4926. $value = stripslashes(substr($value1, 1, -1)).stripslashes(substr($value2, 1, -1)).$value3;
  4927. // Parse array syntax.
  4928. $keys = preg_split('/\]?\[/', rtrim($key, ']'));
  4929. $last = array_pop($keys);
  4930. $parent = &$info;
  4931. // Create nested arrays.
  4932. foreach ($keys as $key) {
  4933. if ($key == '') {
  4934. $key = count($parent);
  4935. }
  4936. if (!isset($parent[$key]) || !is_array($parent[$key])) {
  4937. $parent[$key] = [];
  4938. }
  4939. $parent = &$parent[$key];
  4940. }
  4941. // Handle PHP constants.
  4942. if (defined($value)) {
  4943. $value = constant($value);
  4944. }
  4945. // Insert actual value.
  4946. if ($last == '') {
  4947. $last = count($parent);
  4948. }
  4949. $parent[$last] = $value;
  4950. }
  4951. }
  4952. return $info;
  4953. }
  4954. /**
  4955. * Gets Chamilo version from the configuration files.
  4956. *
  4957. * @return string A string of type "1.8.4", or an empty string if the version could not be found
  4958. */
  4959. function api_get_version()
  4960. {
  4961. return (string) api_get_configuration_value('system_version');
  4962. }
  4963. /**
  4964. * Gets the software name (the name/brand of the Chamilo-based customized system).
  4965. *
  4966. * @return string
  4967. */
  4968. function api_get_software_name()
  4969. {
  4970. $name = api_get_configuration_value('software_name');
  4971. if (!empty($name)) {
  4972. return $name;
  4973. } else {
  4974. return 'Chamilo';
  4975. }
  4976. }
  4977. /**
  4978. * Checks whether status given in parameter exists in the platform.
  4979. *
  4980. * @param mixed the status (can be either int either string)
  4981. *
  4982. * @return bool if the status exists, else returns false
  4983. */
  4984. function api_status_exists($status_asked)
  4985. {
  4986. global $_status_list;
  4987. return in_array($status_asked, $_status_list) ? true : isset($_status_list[$status_asked]);
  4988. }
  4989. /**
  4990. * Checks whether status given in parameter exists in the platform. The function
  4991. * returns the status ID or false if it does not exist, but given the fact there
  4992. * is no "0" status, the return value can be checked against
  4993. * if(api_status_key()) to know if it exists.
  4994. *
  4995. * @param mixed The status (can be either int or string)
  4996. *
  4997. * @return mixed Status ID if exists, false otherwise
  4998. */
  4999. function api_status_key($status)
  5000. {
  5001. global $_status_list;
  5002. return isset($_status_list[$status]) ? $status : array_search($status, $_status_list);
  5003. }
  5004. /**
  5005. * Gets the status langvars list.
  5006. *
  5007. * @return string[] the list of status with their translations
  5008. */
  5009. function api_get_status_langvars()
  5010. {
  5011. return [
  5012. COURSEMANAGER => get_lang('Teacher', ''),
  5013. SESSIONADMIN => get_lang('SessionsAdmin', ''),
  5014. DRH => get_lang('Drh', ''),
  5015. STUDENT => get_lang('Student', ''),
  5016. ANONYMOUS => get_lang('Anonymous', ''),
  5017. STUDENT_BOSS => get_lang('RoleStudentBoss', ''),
  5018. INVITEE => get_lang('Invited'),
  5019. ];
  5020. }
  5021. /**
  5022. * The function that retrieves all the possible settings for a certain config setting.
  5023. *
  5024. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  5025. */
  5026. function api_get_settings_options($var)
  5027. {
  5028. $table_settings_options = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
  5029. $var = Database::escape_string($var);
  5030. $sql = "SELECT * FROM $table_settings_options
  5031. WHERE variable = '$var'
  5032. ORDER BY id";
  5033. $result = Database::query($sql);
  5034. $settings_options_array = [];
  5035. while ($row = Database::fetch_array($result, 'ASSOC')) {
  5036. $settings_options_array[] = $row;
  5037. }
  5038. return $settings_options_array;
  5039. }
  5040. /**
  5041. * @param array $params
  5042. */
  5043. function api_set_setting_option($params)
  5044. {
  5045. $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
  5046. if (empty($params['id'])) {
  5047. Database::insert($table, $params);
  5048. } else {
  5049. Database::update($table, $params, ['id = ? ' => $params['id']]);
  5050. }
  5051. }
  5052. /**
  5053. * @param array $params
  5054. */
  5055. function api_set_setting_simple($params)
  5056. {
  5057. $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  5058. $url_id = api_get_current_access_url_id();
  5059. if (empty($params['id'])) {
  5060. $params['access_url'] = $url_id;
  5061. Database::insert($table, $params);
  5062. } else {
  5063. Database::update($table, $params, ['id = ? ' => [$params['id']]]);
  5064. }
  5065. }
  5066. /**
  5067. * @param int $id
  5068. */
  5069. function api_delete_setting_option($id)
  5070. {
  5071. $table = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
  5072. if (!empty($id)) {
  5073. Database::delete($table, ['id = ? ' => $id]);
  5074. }
  5075. }
  5076. /**
  5077. * Sets a platform configuration setting to a given value.
  5078. *
  5079. * @param string The variable we want to update
  5080. * @param string The value we want to record
  5081. * @param string The sub-variable if any (in most cases, this will remain null)
  5082. * @param string The category if any (in most cases, this will remain null)
  5083. * @param int The access_url for which this parameter is valid
  5084. * @param string $cat
  5085. *
  5086. * @return bool|null
  5087. */
  5088. function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1)
  5089. {
  5090. if (empty($var)) {
  5091. return false;
  5092. }
  5093. $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  5094. $var = Database::escape_string($var);
  5095. $value = Database::escape_string($value);
  5096. $access_url = (int) $access_url;
  5097. if (empty($access_url)) {
  5098. $access_url = 1;
  5099. }
  5100. $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
  5101. if (!empty($subvar)) {
  5102. $subvar = Database::escape_string($subvar);
  5103. $select .= " AND subkey = '$subvar'";
  5104. }
  5105. if (!empty($cat)) {
  5106. $cat = Database::escape_string($cat);
  5107. $select .= " AND category = '$cat'";
  5108. }
  5109. if ($access_url > 1) {
  5110. $select .= " AND access_url = $access_url";
  5111. } else {
  5112. $select .= " AND access_url = 1 ";
  5113. }
  5114. $res = Database::query($select);
  5115. if (Database::num_rows($res) > 0) {
  5116. // Found item for this access_url.
  5117. $row = Database::fetch_array($res);
  5118. $sql = "UPDATE $t_settings SET selected_value = '$value'
  5119. WHERE id = ".$row['id'];
  5120. Database::query($sql);
  5121. } else {
  5122. // Item not found for this access_url, we have to check if it exist with access_url = 1
  5123. $select = "SELECT * FROM $t_settings
  5124. WHERE variable = '$var' AND access_url = 1 ";
  5125. // Just in case
  5126. if ($access_url == 1) {
  5127. if (!empty($subvar)) {
  5128. $select .= " AND subkey = '$subvar'";
  5129. }
  5130. if (!empty($cat)) {
  5131. $select .= " AND category = '$cat'";
  5132. }
  5133. $res = Database::query($select);
  5134. if (Database::num_rows($res) > 0) {
  5135. // We have a setting for access_url 1, but none for the current one, so create one.
  5136. $row = Database::fetch_array($res);
  5137. $insert = "INSERT INTO $t_settings (variable, subkey, type,category, selected_value, title, comment, scope, subkeytext, access_url)
  5138. VALUES
  5139. ('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
  5140. "'".$row['type']."','".$row['category']."',".
  5141. "'$value','".$row['title']."',".
  5142. "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
  5143. "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url)";
  5144. Database::query($insert);
  5145. } else {
  5146. // Such a setting does not exist.
  5147. //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
  5148. }
  5149. } else {
  5150. // Other access url.
  5151. if (!empty($subvar)) {
  5152. $select .= " AND subkey = '$subvar'";
  5153. }
  5154. if (!empty($cat)) {
  5155. $select .= " AND category = '$cat'";
  5156. }
  5157. $res = Database::query($select);
  5158. if (Database::num_rows($res) > 0) {
  5159. // We have a setting for access_url 1, but none for the current one, so create one.
  5160. $row = Database::fetch_array($res);
  5161. if ($row['access_url_changeable'] == 1) {
  5162. $insert = "INSERT INTO $t_settings (variable,subkey, type,category, selected_value,title, comment,scope, subkeytext,access_url, access_url_changeable) VALUES
  5163. ('".$row['variable']."',".
  5164. (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL").",".
  5165. "'".$row['type']."','".$row['category']."',".
  5166. "'$value','".$row['title']."',".
  5167. "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
  5168. (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL").",".
  5169. "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
  5170. Database::query($insert);
  5171. }
  5172. } else { // Such a setting does not exist.
  5173. //error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
  5174. }
  5175. }
  5176. }
  5177. }
  5178. /**
  5179. * Sets a whole category of settings to one specific value.
  5180. *
  5181. * @param string Category
  5182. * @param string Value
  5183. * @param int Access URL. Optional. Defaults to 1
  5184. * @param array Optional array of filters on field type
  5185. * @param string $category
  5186. * @param string $value
  5187. *
  5188. * @return bool
  5189. */
  5190. function api_set_settings_category($category, $value = null, $access_url = 1, $fieldtype = [])
  5191. {
  5192. if (empty($category)) {
  5193. return false;
  5194. }
  5195. $category = Database::escape_string($category);
  5196. $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  5197. $access_url = (int) $access_url;
  5198. if (empty($access_url)) {
  5199. $access_url = 1;
  5200. }
  5201. if (isset($value)) {
  5202. $value = Database::escape_string($value);
  5203. $sql = "UPDATE $t_s SET selected_value = '$value'
  5204. WHERE category = '$category' AND access_url = $access_url";
  5205. if (is_array($fieldtype) && count($fieldtype) > 0) {
  5206. $sql .= " AND ( ";
  5207. $i = 0;
  5208. foreach ($fieldtype as $type) {
  5209. if ($i > 0) {
  5210. $sql .= ' OR ';
  5211. }
  5212. $type = Database::escape_string($type);
  5213. $sql .= " type='".$type."' ";
  5214. $i++;
  5215. }
  5216. $sql .= ")";
  5217. }
  5218. $res = Database::query($sql);
  5219. return $res !== false;
  5220. } else {
  5221. $sql = "UPDATE $t_s SET selected_value = NULL
  5222. WHERE category = '$category' AND access_url = $access_url";
  5223. if (is_array($fieldtype) && count($fieldtype) > 0) {
  5224. $sql .= " AND ( ";
  5225. $i = 0;
  5226. foreach ($fieldtype as $type) {
  5227. if ($i > 0) {
  5228. $sql .= ' OR ';
  5229. }
  5230. $type = Database::escape_string($type);
  5231. $sql .= " type='".$type."' ";
  5232. $i++;
  5233. }
  5234. $sql .= ")";
  5235. }
  5236. $res = Database::query($sql);
  5237. return $res !== false;
  5238. }
  5239. }
  5240. /**
  5241. * Gets all available access urls in an array (as in the database).
  5242. *
  5243. * @return array An array of database records
  5244. */
  5245. function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC')
  5246. {
  5247. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
  5248. $from = (int) $from;
  5249. $to = (int) $to;
  5250. $order = Database::escape_string($order, null, false);
  5251. $direction = Database::escape_string($direction, null, false);
  5252. $sql = "SELECT id, url, description, active, created_by, tms
  5253. FROM $table
  5254. ORDER BY $order $direction
  5255. LIMIT $to OFFSET $from";
  5256. $res = Database::query($sql);
  5257. return Database::store_result($res);
  5258. }
  5259. /**
  5260. * Gets the access url info in an array.
  5261. *
  5262. * @param int $id Id of the access url
  5263. * @param bool $returnDefault Set to false if you want the real URL if URL 1 is still 'http://localhost/'
  5264. *
  5265. * @return array All the info (url, description, active, created_by, tms)
  5266. * from the access_url table
  5267. *
  5268. * @author Julio Montoya
  5269. */
  5270. function api_get_access_url($id, $returnDefault = true)
  5271. {
  5272. static $staticResult;
  5273. $id = (int) $id;
  5274. if (isset($staticResult[$id])) {
  5275. $result = $staticResult[$id];
  5276. } else {
  5277. // Calling the Database:: library dont work this is handmade.
  5278. $table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
  5279. $sql = "SELECT url, description, active, created_by, tms
  5280. FROM $table_access_url WHERE id = '$id' ";
  5281. $res = Database::query($sql);
  5282. $result = @Database::fetch_array($res);
  5283. $staticResult[$id] = $result;
  5284. }
  5285. // If the result url is 'http://localhost/' (the default) and the root_web
  5286. // (=current url) is different, and the $id is = 1 (which might mean
  5287. // api_get_current_access_url_id() returned 1 by default), then return the
  5288. // root_web setting instead of the current URL
  5289. // This is provided as an option to avoid breaking the storage of URL-specific
  5290. // homepages in home/localhost/
  5291. if ($id === 1 && $returnDefault === false) {
  5292. $currentUrl = api_get_current_access_url_id();
  5293. // only do this if we are on the main URL (=1), otherwise we could get
  5294. // information on another URL instead of the one asked as parameter
  5295. if ($currentUrl === 1) {
  5296. $rootWeb = api_get_path(WEB_PATH);
  5297. $default = 'http://localhost/';
  5298. if ($result['url'] === $default && $rootWeb != $default) {
  5299. $result['url'] = $rootWeb;
  5300. }
  5301. }
  5302. }
  5303. return $result;
  5304. }
  5305. /**
  5306. * Gets all the current settings for a specific access url.
  5307. *
  5308. * @param string The category, if any, that we want to get
  5309. * @param string Whether we want a simple list (display a category) or
  5310. * a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
  5311. * @param int Access URL's ID. Optional. Uses 1 by default, which is the unique URL
  5312. *
  5313. * @return array Array of database results for the current settings of the current access URL
  5314. */
  5315. function &api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0)
  5316. {
  5317. $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  5318. $access_url = (int) $access_url;
  5319. $where_condition = '';
  5320. if ($url_changeable == 1) {
  5321. $where_condition = " AND access_url_changeable= '1' ";
  5322. }
  5323. if (empty($access_url) || $access_url == -1) {
  5324. $access_url = 1;
  5325. }
  5326. $sql = "SELECT * FROM $table
  5327. WHERE access_url = $access_url $where_condition ";
  5328. if (!empty($cat)) {
  5329. $cat = Database::escape_string($cat);
  5330. $sql .= " AND category='$cat' ";
  5331. }
  5332. if ($ordering == 'group') {
  5333. $sql .= " ORDER BY id ASC";
  5334. } else {
  5335. $sql .= " ORDER BY 1,2 ASC";
  5336. }
  5337. $result = Database::query($sql);
  5338. if ($result === null) {
  5339. return [];
  5340. }
  5341. $result = Database::store_result($result, 'ASSOC');
  5342. return $result;
  5343. }
  5344. /**
  5345. * @param string $value The value we want to record
  5346. * @param string $variable The variable name we want to insert
  5347. * @param string $subKey The subkey for the variable we want to insert
  5348. * @param string $type The type for the variable we want to insert
  5349. * @param string $category The category for the variable we want to insert
  5350. * @param string $title The title
  5351. * @param string $comment The comment
  5352. * @param string $scope The scope
  5353. * @param string $subKeyText The subkey text
  5354. * @param int $accessUrlId The access_url for which this parameter is valid
  5355. * @param int $visibility The changeability of this setting for non-master urls
  5356. *
  5357. * @return int The setting ID
  5358. */
  5359. function api_add_setting(
  5360. $value,
  5361. $variable,
  5362. $subKey = '',
  5363. $type = 'textfield',
  5364. $category = '',
  5365. $title = '',
  5366. $comment = '',
  5367. $scope = '',
  5368. $subKeyText = '',
  5369. $accessUrlId = 1,
  5370. $visibility = 0
  5371. ) {
  5372. $em = Database::getManager();
  5373. $settingRepo = $em->getRepository('ChamiloCoreBundle:SettingsCurrent');
  5374. $accessUrlId = (int) $accessUrlId ?: 1;
  5375. if (is_array($value)) {
  5376. $value = serialize($value);
  5377. } else {
  5378. $value = trim($value);
  5379. }
  5380. $criteria = ['variable' => $variable, 'url' => $accessUrlId];
  5381. if (!empty($subKey)) {
  5382. $criteria['subkey'] = $subKey;
  5383. }
  5384. // Check if this variable doesn't exist already
  5385. /** @var SettingsCurrent $setting */
  5386. $setting = $settingRepo->findOneBy($criteria);
  5387. if ($setting) {
  5388. $setting->setSelectedValue($value);
  5389. $em->persist($setting);
  5390. $em->flush();
  5391. return $setting->getId();
  5392. }
  5393. // Item not found for this access_url, we have to check if the whole thing is missing
  5394. // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
  5395. $setting = new SettingsCurrent();
  5396. $url = api_get_url_entity();
  5397. $setting
  5398. ->setVariable($variable)
  5399. ->setSelectedValue($value)
  5400. ->setType($type)
  5401. ->setCategory($category)
  5402. ->setSubkey($subKey)
  5403. ->setTitle($title)
  5404. ->setComment($comment)
  5405. ->setScope($scope)
  5406. ->setSubkeytext($subKeyText)
  5407. ->setUrl(api_get_url_entity())
  5408. ->setAccessUrlChangeable($visibility);
  5409. $em->persist($setting);
  5410. $em->flush();
  5411. return $setting->getId();
  5412. }
  5413. /**
  5414. * Checks wether a user can or can't view the contents of a course.
  5415. *
  5416. * @deprecated use CourseManager::is_user_subscribed_in_course
  5417. *
  5418. * @param int $userid User id or NULL to get it from $_SESSION
  5419. * @param int $cid course id to check whether the user is allowed
  5420. *
  5421. * @return bool
  5422. */
  5423. function api_is_course_visible_for_user($userid = null, $cid = null)
  5424. {
  5425. if ($userid === null) {
  5426. $userid = api_get_user_id();
  5427. }
  5428. if (empty($userid) || strval(intval($userid)) != $userid) {
  5429. if (api_is_anonymous()) {
  5430. $userid = api_get_anonymous_id();
  5431. } else {
  5432. return false;
  5433. }
  5434. }
  5435. $cid = Database::escape_string($cid);
  5436. $courseInfo = api_get_course_info($cid);
  5437. $courseId = $courseInfo['real_id'];
  5438. $is_platformAdmin = api_is_platform_admin();
  5439. $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
  5440. $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  5441. $sql = "SELECT
  5442. $course_table.category_code,
  5443. $course_table.visibility,
  5444. $course_table.code,
  5445. $course_cat_table.code
  5446. FROM $course_table
  5447. LEFT JOIN $course_cat_table
  5448. ON $course_table.category_code = $course_cat_table.code
  5449. WHERE
  5450. $course_table.code = '$cid'
  5451. LIMIT 1";
  5452. $result = Database::query($sql);
  5453. if (Database::num_rows($result) > 0) {
  5454. $visibility = Database::fetch_array($result);
  5455. $visibility = $visibility['visibility'];
  5456. } else {
  5457. $visibility = 0;
  5458. }
  5459. // Shortcut permissions in case the visibility is "open to the world".
  5460. if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
  5461. return true;
  5462. }
  5463. $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  5464. $sql = "SELECT
  5465. is_tutor, status
  5466. FROM $tbl_course_user
  5467. WHERE
  5468. user_id = '$userid' AND
  5469. relation_type <> '".COURSE_RELATION_TYPE_RRHH."' AND
  5470. c_id = $courseId
  5471. LIMIT 1";
  5472. $result = Database::query($sql);
  5473. if (Database::num_rows($result) > 0) {
  5474. // This user has got a recorded state for this course.
  5475. $cuData = Database::fetch_array($result);
  5476. $is_courseMember = true;
  5477. $is_courseAdmin = ($cuData['status'] == 1);
  5478. }
  5479. if (!$is_courseAdmin) {
  5480. // This user has no status related to this course.
  5481. // Is it the session coach or the session admin?
  5482. $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
  5483. $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
  5484. $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
  5485. $sql = "SELECT
  5486. session.id_coach, session_admin_id, session.id
  5487. FROM
  5488. $tbl_session as session
  5489. INNER JOIN $tbl_session_course
  5490. ON session_rel_course.session_id = session.id
  5491. AND session_rel_course.c_id = '$courseId'
  5492. LIMIT 1";
  5493. $result = Database::query($sql);
  5494. $row = Database::store_result($result);
  5495. if ($row[0]['id_coach'] == $userid) {
  5496. $is_courseMember = true;
  5497. $is_courseAdmin = false;
  5498. } elseif ($row[0]['session_admin_id'] == $userid) {
  5499. $is_courseMember = false;
  5500. $is_courseAdmin = false;
  5501. } else {
  5502. // Check if the current user is the course coach.
  5503. $sql = "SELECT 1
  5504. FROM $tbl_session_course
  5505. WHERE session_rel_course.c_id = '$courseId'
  5506. AND session_rel_course.id_coach = '$userid'
  5507. LIMIT 1";
  5508. $result = Database::query($sql);
  5509. //if ($row = Database::fetch_array($result)) {
  5510. if (Database::num_rows($result) > 0) {
  5511. $is_courseMember = true;
  5512. $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
  5513. $sql = "SELECT status FROM $tbl_user
  5514. WHERE user_id = $userid
  5515. LIMIT 1";
  5516. $result = Database::query($sql);
  5517. if (Database::result($result, 0, 0) == 1) {
  5518. $is_courseAdmin = true;
  5519. } else {
  5520. $is_courseAdmin = false;
  5521. }
  5522. } else {
  5523. // Check if the user is a student is this session.
  5524. $sql = "SELECT id
  5525. FROM $tbl_session_course_user
  5526. WHERE
  5527. user_id = '$userid' AND
  5528. c_id = '$courseId'
  5529. LIMIT 1";
  5530. if (Database::num_rows($result) > 0) {
  5531. // This user haa got a recorded state for this course.
  5532. while ($row = Database::fetch_array($result)) {
  5533. $is_courseMember = true;
  5534. $is_courseAdmin = false;
  5535. }
  5536. }
  5537. }
  5538. }
  5539. }
  5540. switch ($visibility) {
  5541. case COURSE_VISIBILITY_OPEN_WORLD:
  5542. return true;
  5543. case COURSE_VISIBILITY_OPEN_PLATFORM:
  5544. return isset($userid);
  5545. case COURSE_VISIBILITY_REGISTERED:
  5546. case COURSE_VISIBILITY_CLOSED:
  5547. return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
  5548. case COURSE_VISIBILITY_HIDDEN:
  5549. return $is_platformAdmin;
  5550. }
  5551. return false;
  5552. }
  5553. /**
  5554. * Returns whether an element (forum, message, survey ...) belongs to a session or not.
  5555. *
  5556. * @param string the tool of the element
  5557. * @param int the element id in database
  5558. * @param int the session_id to compare with element session id
  5559. *
  5560. * @return bool true if the element is in the session, false else
  5561. */
  5562. function api_is_element_in_the_session($tool, $element_id, $session_id = null)
  5563. {
  5564. if (is_null($session_id)) {
  5565. $session_id = api_get_session_id();
  5566. }
  5567. $element_id = (int) $element_id;
  5568. if (empty($element_id)) {
  5569. return false;
  5570. }
  5571. // Get information to build query depending of the tool.
  5572. switch ($tool) {
  5573. case TOOL_SURVEY:
  5574. $table_tool = Database::get_course_table(TABLE_SURVEY);
  5575. $key_field = 'survey_id';
  5576. break;
  5577. case TOOL_ANNOUNCEMENT:
  5578. $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
  5579. $key_field = 'id';
  5580. break;
  5581. case TOOL_AGENDA:
  5582. $table_tool = Database::get_course_table(TABLE_AGENDA);
  5583. $key_field = 'id';
  5584. break;
  5585. case TOOL_GROUP:
  5586. $table_tool = Database::get_course_table(TABLE_GROUP);
  5587. $key_field = 'id';
  5588. break;
  5589. default:
  5590. return false;
  5591. }
  5592. $course_id = api_get_course_int_id();
  5593. $sql = "SELECT session_id FROM $table_tool
  5594. WHERE c_id = $course_id AND $key_field = ".$element_id;
  5595. $rs = Database::query($sql);
  5596. if ($element_session_id = Database::result($rs, 0, 0)) {
  5597. if ($element_session_id == intval($session_id)) {
  5598. // The element belongs to the session.
  5599. return true;
  5600. }
  5601. }
  5602. return false;
  5603. }
  5604. /**
  5605. * Replaces "forbidden" characters in a filename string.
  5606. *
  5607. * @param string $filename
  5608. * @param bool $treat_spaces_as_hyphens
  5609. *
  5610. * @return string
  5611. */
  5612. function api_replace_dangerous_char($filename, $treat_spaces_as_hyphens = true)
  5613. {
  5614. // Some non-properly encoded file names can cause the whole file to be
  5615. // skipped when uploaded. Avoid this by detecting the encoding and
  5616. // converting to UTF-8, setting the source as ASCII (a reasonably
  5617. // limited characters set) if nothing could be found (BT#
  5618. $encoding = api_detect_encoding($filename);
  5619. if (empty($encoding)) {
  5620. $encoding = 'ASCII';
  5621. if (!api_is_valid_ascii($filename)) {
  5622. // try iconv and try non standard ASCII a.k.a CP437
  5623. // see BT#15022
  5624. if (function_exists('iconv')) {
  5625. $result = iconv('CP437', 'UTF-8', $filename);
  5626. if (api_is_valid_utf8($result)) {
  5627. $filename = $result;
  5628. $encoding = 'UTF-8';
  5629. }
  5630. }
  5631. }
  5632. }
  5633. $filename = api_to_system_encoding($filename, $encoding);
  5634. $url = URLify::filter(
  5635. $filename,
  5636. 250,
  5637. '',
  5638. true,
  5639. true,
  5640. false,
  5641. false,
  5642. $treat_spaces_as_hyphens
  5643. );
  5644. return $url;
  5645. }
  5646. /**
  5647. * Fixes the $_SERVER['REQUEST_URI'] that is empty in IIS6.
  5648. *
  5649. * @author Ivan Tcholakov, 28-JUN-2006.
  5650. */
  5651. function api_request_uri()
  5652. {
  5653. if (!empty($_SERVER['REQUEST_URI'])) {
  5654. return $_SERVER['REQUEST_URI'];
  5655. }
  5656. $uri = $_SERVER['SCRIPT_NAME'];
  5657. if (!empty($_SERVER['QUERY_STRING'])) {
  5658. $uri .= '?'.$_SERVER['QUERY_STRING'];
  5659. }
  5660. $_SERVER['REQUEST_URI'] = $uri;
  5661. return $uri;
  5662. }
  5663. /** Gets the current access_url id of the Chamilo Platform
  5664. * @author Julio Montoya <gugli100@gmail.com>
  5665. *
  5666. * @return int access_url_id of the current Chamilo Installation
  5667. */
  5668. function api_get_current_access_url_id()
  5669. {
  5670. if (api_get_multiple_access_url() === false) {
  5671. return 1;
  5672. }
  5673. static $id;
  5674. if (!empty($id)) {
  5675. return $id;
  5676. }
  5677. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
  5678. $path = Database::escape_string(api_get_path(WEB_PATH));
  5679. $sql = "SELECT id FROM $table WHERE url = '".$path."'";
  5680. $result = Database::query($sql);
  5681. if (Database::num_rows($result) > 0) {
  5682. $id = Database::result($result, 0, 0);
  5683. if ($id === false) {
  5684. return -1;
  5685. }
  5686. return (int) $id;
  5687. }
  5688. $id = 1;
  5689. //if the url in WEB_PATH was not found, it can only mean that there is
  5690. // either a configuration problem or the first URL has not been defined yet
  5691. // (by default it is http://localhost/). Thus the more sensible thing we can
  5692. // do is return 1 (the main URL) as the user cannot hack this value anyway
  5693. return 1;
  5694. }
  5695. /**
  5696. * Gets the registered urls from a given user id.
  5697. *
  5698. * @author Julio Montoya <gugli100@gmail.com>
  5699. *
  5700. * @param int $user_id
  5701. *
  5702. * @return array
  5703. */
  5704. function api_get_access_url_from_user($user_id)
  5705. {
  5706. $user_id = (int) $user_id;
  5707. $table_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
  5708. $table_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
  5709. $sql = "SELECT access_url_id
  5710. FROM $table_url_rel_user url_rel_user
  5711. INNER JOIN $table_url u
  5712. ON (url_rel_user.access_url_id = u.id)
  5713. WHERE user_id = ".$user_id;
  5714. $result = Database::query($sql);
  5715. $list = [];
  5716. while ($row = Database::fetch_array($result, 'ASSOC')) {
  5717. $list[] = $row['access_url_id'];
  5718. }
  5719. return $list;
  5720. }
  5721. /**
  5722. * Gets the status of a user in a course.
  5723. *
  5724. * @param int $user_id
  5725. * @param int $courseId
  5726. *
  5727. * @return int user status
  5728. */
  5729. function api_get_status_of_user_in_course($user_id, $courseId)
  5730. {
  5731. $tbl_rel_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  5732. if (!empty($user_id) && !empty($courseId)) {
  5733. $user_id = intval($user_id);
  5734. $courseId = intval($courseId);
  5735. $sql = 'SELECT status
  5736. FROM '.$tbl_rel_course_user.'
  5737. WHERE user_id='.$user_id.' AND c_id = '.$courseId;
  5738. $result = Database::query($sql);
  5739. $row_status = Database::fetch_array($result, 'ASSOC');
  5740. return $row_status['status'];
  5741. } else {
  5742. return 0;
  5743. }
  5744. }
  5745. /**
  5746. * Checks whether the curent user is in a group or not.
  5747. *
  5748. * @param string The group id - optional (takes it from session if not given)
  5749. * @param string The course code - optional (no additional check by course if course code is not given)
  5750. *
  5751. * @return bool
  5752. *
  5753. * @author Ivan Tcholakov
  5754. */
  5755. function api_is_in_group($groupIdParam = null, $courseCodeParam = null)
  5756. {
  5757. if (!empty($courseCodeParam)) {
  5758. $courseCode = api_get_course_id();
  5759. if (!empty($courseCode)) {
  5760. if ($courseCodeParam != $courseCode) {
  5761. return false;
  5762. }
  5763. } else {
  5764. return false;
  5765. }
  5766. }
  5767. $groupId = api_get_group_id();
  5768. if (isset($groupId) && $groupId != '') {
  5769. if (!empty($groupIdParam)) {
  5770. return $groupIdParam == $groupId;
  5771. } else {
  5772. return true;
  5773. }
  5774. }
  5775. return false;
  5776. }
  5777. /**
  5778. * Checks whether a secret key is valid.
  5779. *
  5780. * @param string $original_key_secret - secret key from (webservice) client
  5781. * @param string $security_key - security key from Chamilo
  5782. *
  5783. * @return bool - true if secret key is valid, false otherwise
  5784. */
  5785. function api_is_valid_secret_key($original_key_secret, $security_key)
  5786. {
  5787. return $original_key_secret == sha1($security_key);
  5788. }
  5789. /**
  5790. * Checks whether a user is into course.
  5791. *
  5792. * @param int $course_id - the course id
  5793. * @param int $user_id - the user id
  5794. *
  5795. * @return bool
  5796. */
  5797. function api_is_user_of_course($course_id, $user_id)
  5798. {
  5799. $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  5800. $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.'
  5801. WHERE
  5802. c_id ="'.intval($course_id).'" AND
  5803. user_id = "'.intval($user_id).'" AND
  5804. relation_type <> '.COURSE_RELATION_TYPE_RRHH.' ';
  5805. $result = Database::query($sql);
  5806. return Database::num_rows($result) == 1;
  5807. }
  5808. /**
  5809. * Checks whether the server's operating system is Windows (TM).
  5810. *
  5811. * @return bool - true if the operating system is Windows, false otherwise
  5812. */
  5813. function api_is_windows_os()
  5814. {
  5815. if (function_exists('php_uname')) {
  5816. // php_uname() exists as of PHP 4.0.2, according to the documentation.
  5817. // We expect that this function will always work for Chamilo 1.8.x.
  5818. $os = php_uname();
  5819. }
  5820. // The following methods are not needed, but let them stay, just in case.
  5821. elseif (isset($_ENV['OS'])) {
  5822. // Sometimes $_ENV['OS'] may not be present (bugs?)
  5823. $os = $_ENV['OS'];
  5824. } elseif (defined('PHP_OS')) {
  5825. // PHP_OS means on which OS PHP was compiled, this is why
  5826. // using PHP_OS is the last choice for detection.
  5827. $os = PHP_OS;
  5828. } else {
  5829. return false;
  5830. }
  5831. return strtolower(substr((string) $os, 0, 3)) == 'win';
  5832. }
  5833. /**
  5834. * This function informs whether the sent request is XMLHttpRequest.
  5835. */
  5836. function api_is_xml_http_request()
  5837. {
  5838. return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
  5839. }
  5840. /**
  5841. * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
  5842. *
  5843. * @see http://php.net/manual/en/function.getimagesize.php
  5844. * @see http://www.dokeos.com/forum/viewtopic.php?t=12345
  5845. * @see http://www.dokeos.com/forum/viewtopic.php?t=16355
  5846. *
  5847. * @return int
  5848. */
  5849. function api_getimagesize($path)
  5850. {
  5851. $image = new Image($path);
  5852. return $image->get_image_size();
  5853. }
  5854. /**
  5855. * This function resizes an image, with preserving its proportions (or aspect ratio).
  5856. *
  5857. * @author Ivan Tcholakov, MAY-2009.
  5858. *
  5859. * @param int $image System path or URL of the image
  5860. * @param int $target_width Targeted width
  5861. * @param int $target_height Targeted height
  5862. *
  5863. * @return array Calculated new width and height
  5864. */
  5865. function api_resize_image($image, $target_width, $target_height)
  5866. {
  5867. $image_properties = api_getimagesize($image);
  5868. return api_calculate_image_size(
  5869. $image_properties['width'],
  5870. $image_properties['height'],
  5871. $target_width,
  5872. $target_height
  5873. );
  5874. }
  5875. /**
  5876. * This function calculates new image size, with preserving image's proportions (or aspect ratio).
  5877. *
  5878. * @author Ivan Tcholakov, MAY-2009.
  5879. * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
  5880. *
  5881. * @param int $image_width Initial width
  5882. * @param int $image_height Initial height
  5883. * @param int $target_width Targeted width
  5884. * @param int $target_height Targeted height
  5885. *
  5886. * @return array Calculated new width and height
  5887. */
  5888. function api_calculate_image_size(
  5889. $image_width,
  5890. $image_height,
  5891. $target_width,
  5892. $target_height
  5893. ) {
  5894. // Only maths is here.
  5895. $result = ['width' => $image_width, 'height' => $image_height];
  5896. if ($image_width <= 0 || $image_height <= 0) {
  5897. return $result;
  5898. }
  5899. $resize_factor_width = $target_width / $image_width;
  5900. $resize_factor_height = $target_height / $image_height;
  5901. $delta_width = $target_width - $image_width * $resize_factor_height;
  5902. $delta_height = $target_height - $image_height * $resize_factor_width;
  5903. if ($delta_width > $delta_height) {
  5904. $result['width'] = ceil($image_width * $resize_factor_height);
  5905. $result['height'] = ceil($image_height * $resize_factor_height);
  5906. } elseif ($delta_width < $delta_height) {
  5907. $result['width'] = ceil($image_width * $resize_factor_width);
  5908. $result['height'] = ceil($image_height * $resize_factor_width);
  5909. } else {
  5910. $result['width'] = ceil($target_width);
  5911. $result['height'] = ceil($target_height);
  5912. }
  5913. return $result;
  5914. }
  5915. /**
  5916. * Returns a list of Chamilo's tools or
  5917. * checks whether a given identificator is a valid Chamilo's tool.
  5918. *
  5919. * @author Isaac flores paz
  5920. *
  5921. * @param string The tool name to filter
  5922. *
  5923. * @return mixed Filtered string or array
  5924. */
  5925. function api_get_tools_lists($my_tool = null)
  5926. {
  5927. $tools_list = [
  5928. TOOL_DOCUMENT,
  5929. TOOL_THUMBNAIL,
  5930. TOOL_HOTPOTATOES,
  5931. TOOL_CALENDAR_EVENT,
  5932. TOOL_LINK,
  5933. TOOL_COURSE_DESCRIPTION,
  5934. TOOL_SEARCH,
  5935. TOOL_LEARNPATH,
  5936. TOOL_ANNOUNCEMENT,
  5937. TOOL_FORUM,
  5938. TOOL_THREAD,
  5939. TOOL_POST,
  5940. TOOL_DROPBOX,
  5941. TOOL_QUIZ,
  5942. TOOL_USER,
  5943. TOOL_GROUP,
  5944. TOOL_BLOGS,
  5945. TOOL_CHAT,
  5946. TOOL_STUDENTPUBLICATION,
  5947. TOOL_TRACKING,
  5948. TOOL_HOMEPAGE_LINK,
  5949. TOOL_COURSE_SETTING,
  5950. TOOL_BACKUP,
  5951. TOOL_COPY_COURSE_CONTENT,
  5952. TOOL_RECYCLE_COURSE,
  5953. TOOL_COURSE_HOMEPAGE,
  5954. TOOL_COURSE_RIGHTS_OVERVIEW,
  5955. TOOL_UPLOAD,
  5956. TOOL_COURSE_MAINTENANCE,
  5957. TOOL_SURVEY,
  5958. TOOL_WIKI,
  5959. TOOL_GLOSSARY,
  5960. TOOL_GRADEBOOK,
  5961. TOOL_NOTEBOOK,
  5962. TOOL_ATTENDANCE,
  5963. TOOL_COURSE_PROGRESS,
  5964. ];
  5965. if (empty($my_tool)) {
  5966. return $tools_list;
  5967. }
  5968. return in_array($my_tool, $tools_list) ? $my_tool : '';
  5969. }
  5970. /**
  5971. * Checks whether we already approved the last version term and condition.
  5972. *
  5973. * @param int user id
  5974. *
  5975. * @return bool true if we pass false otherwise
  5976. */
  5977. function api_check_term_condition($userId)
  5978. {
  5979. if (api_get_setting('allow_terms_conditions') === 'true') {
  5980. // Check if exists terms and conditions
  5981. if (LegalManager::count() == 0) {
  5982. return true;
  5983. }
  5984. $extraFieldValue = new ExtraFieldValue('user');
  5985. $data = $extraFieldValue->get_values_by_handler_and_field_variable(
  5986. $userId,
  5987. 'legal_accept'
  5988. );
  5989. if (!empty($data) && isset($data['value']) && !empty($data['value'])) {
  5990. $result = $data['value'];
  5991. $user_conditions = explode(':', $result);
  5992. $version = $user_conditions[0];
  5993. $langId = $user_conditions[1];
  5994. $realVersion = LegalManager::get_last_version($langId);
  5995. return $version >= $realVersion;
  5996. }
  5997. return false;
  5998. }
  5999. return false;
  6000. }
  6001. /**
  6002. * Gets all information of a tool into course.
  6003. *
  6004. * @param int The tool id
  6005. *
  6006. * @return array
  6007. */
  6008. function api_get_tool_information_by_name($name)
  6009. {
  6010. $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
  6011. $course_id = api_get_course_int_id();
  6012. $sql = "SELECT * FROM $t_tool
  6013. WHERE c_id = $course_id AND name = '".Database::escape_string($name)."' ";
  6014. $rs = Database::query($sql);
  6015. return Database::fetch_array($rs, 'ASSOC');
  6016. }
  6017. /**
  6018. * Function used to protect a "global" admin script.
  6019. * The function blocks access when the user has no global platform admin rights.
  6020. * Global admins are the admins that are registered in the main.admin table
  6021. * AND the users who have access to the "principal" portal.
  6022. * That means that there is a record in the main.access_url_rel_user table
  6023. * with his user id and the access_url_id=1.
  6024. *
  6025. * @author Julio Montoya
  6026. *
  6027. * @param int $user_id
  6028. *
  6029. * @return bool
  6030. */
  6031. function api_is_global_platform_admin($user_id = null)
  6032. {
  6033. $user_id = (int) $user_id;
  6034. if (empty($user_id)) {
  6035. $user_id = api_get_user_id();
  6036. }
  6037. if (api_is_platform_admin_by_id($user_id)) {
  6038. $urlList = api_get_access_url_from_user($user_id);
  6039. // The admin is registered in the first "main" site with access_url_id = 1
  6040. if (in_array(1, $urlList)) {
  6041. return true;
  6042. } else {
  6043. return false;
  6044. }
  6045. }
  6046. return false;
  6047. }
  6048. /**
  6049. * @param int $admin_id_to_check
  6050. * @param int $my_user_id
  6051. * @param bool $allow_session_admin
  6052. *
  6053. * @return bool
  6054. */
  6055. function api_global_admin_can_edit_admin(
  6056. $admin_id_to_check,
  6057. $my_user_id = null,
  6058. $allow_session_admin = false
  6059. ) {
  6060. if (empty($my_user_id)) {
  6061. $my_user_id = api_get_user_id();
  6062. }
  6063. $iam_a_global_admin = api_is_global_platform_admin($my_user_id);
  6064. $user_is_global_admin = api_is_global_platform_admin($admin_id_to_check);
  6065. if ($iam_a_global_admin) {
  6066. // Global admin can edit everything
  6067. return true;
  6068. } else {
  6069. // If i'm a simple admin
  6070. $is_platform_admin = api_is_platform_admin_by_id($my_user_id);
  6071. if ($allow_session_admin) {
  6072. $is_platform_admin = api_is_platform_admin_by_id($my_user_id) || (api_get_user_status($my_user_id) == SESSIONADMIN);
  6073. }
  6074. if ($is_platform_admin) {
  6075. if ($user_is_global_admin) {
  6076. return false;
  6077. } else {
  6078. return true;
  6079. }
  6080. } else {
  6081. return false;
  6082. }
  6083. }
  6084. }
  6085. /**
  6086. * @param int $admin_id_to_check
  6087. * @param int $my_user_id
  6088. * @param bool $allow_session_admin
  6089. *
  6090. * @return bool|null
  6091. */
  6092. function api_protect_super_admin($admin_id_to_check, $my_user_id = null, $allow_session_admin = false)
  6093. {
  6094. if (api_global_admin_can_edit_admin($admin_id_to_check, $my_user_id, $allow_session_admin)) {
  6095. return true;
  6096. } else {
  6097. api_not_allowed();
  6098. }
  6099. }
  6100. /**
  6101. * Function used to protect a global admin script.
  6102. * The function blocks access when the user has no global platform admin rights.
  6103. * See also the api_is_global_platform_admin() function wich defines who's a "global" admin.
  6104. *
  6105. * @author Julio Montoya
  6106. */
  6107. function api_protect_global_admin_script()
  6108. {
  6109. if (!api_is_global_platform_admin()) {
  6110. api_not_allowed();
  6111. return false;
  6112. }
  6113. return true;
  6114. }
  6115. /**
  6116. * Get active template.
  6117. *
  6118. * @param string theme type (optional: default)
  6119. * @param string path absolute(abs) or relative(rel) (optional:rel)
  6120. *
  6121. * @return string actived template path
  6122. */
  6123. function api_get_template($path_type = 'rel')
  6124. {
  6125. $path_types = ['rel', 'abs'];
  6126. $template_path = '';
  6127. if (in_array($path_type, $path_types)) {
  6128. if ($path_type == 'rel') {
  6129. $template_path = api_get_path(SYS_TEMPLATE_PATH);
  6130. } else {
  6131. $template_path = api_get_path(WEB_TEMPLATE_PATH);
  6132. }
  6133. }
  6134. $actived_theme = 'default';
  6135. if (api_get_setting('active_template')) {
  6136. $actived_theme = api_get_setting('active_template');
  6137. }
  6138. $actived_theme_path = $template_path.$actived_theme.DIRECTORY_SEPARATOR;
  6139. return $actived_theme_path;
  6140. }
  6141. /**
  6142. * Check browser support for specific file types or features
  6143. * This function checks if the user's browser supports a file format or given
  6144. * feature, or returns the current browser and major version when
  6145. * $format=check_browser. Only a limited number of formats and features are
  6146. * checked by this method. Make sure you check its definition first.
  6147. *
  6148. * @param string $format Can be a file format (extension like svg, webm, ...) or a feature (like autocapitalize, ...)
  6149. *
  6150. * @return bool or return text array if $format=check_browser
  6151. *
  6152. * @author Juan Carlos Raña Trabado
  6153. */
  6154. function api_browser_support($format = '')
  6155. {
  6156. $browser = new Browser();
  6157. $current_browser = $browser->getBrowser();
  6158. $a_versiontemp = explode('.', $browser->getVersion());
  6159. $current_majorver = $a_versiontemp[0];
  6160. static $result;
  6161. if (isset($result[$format])) {
  6162. return $result[$format];
  6163. }
  6164. // Native svg support
  6165. if ($format == 'svg') {
  6166. if (($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
  6167. ($current_browser == 'Firefox' && $current_majorver > 1) ||
  6168. ($current_browser == 'Safari' && $current_majorver >= 4) ||
  6169. ($current_browser == 'Chrome' && $current_majorver >= 1) ||
  6170. ($current_browser == 'Opera' && $current_majorver >= 9)
  6171. ) {
  6172. $result[$format] = true;
  6173. return true;
  6174. } else {
  6175. $result[$format] = false;
  6176. return false;
  6177. }
  6178. } elseif ($format == 'pdf') {
  6179. // native pdf support
  6180. if ($current_browser == 'Chrome' && $current_majorver >= 6) {
  6181. $result[$format] = true;
  6182. return true;
  6183. } else {
  6184. $result[$format] = false;
  6185. return false;
  6186. }
  6187. } elseif ($format == 'tif' || $format == 'tiff') {
  6188. //native tif support
  6189. if ($current_browser == 'Safari' && $current_majorver >= 5) {
  6190. $result[$format] = true;
  6191. return true;
  6192. } else {
  6193. $result[$format] = false;
  6194. return false;
  6195. }
  6196. } elseif ($format == 'ogg' || $format == 'ogx' || $format == 'ogv' || $format == 'oga') {
  6197. //native ogg, ogv,oga support
  6198. if (($current_browser == 'Firefox' && $current_majorver >= 3) ||
  6199. ($current_browser == 'Chrome' && $current_majorver >= 3) ||
  6200. ($current_browser == 'Opera' && $current_majorver >= 9)) {
  6201. $result[$format] = true;
  6202. return true;
  6203. } else {
  6204. $result[$format] = false;
  6205. return false;
  6206. }
  6207. } elseif ($format == 'mpg' || $format == 'mpeg') {
  6208. //native mpg support
  6209. if (($current_browser == 'Safari' && $current_majorver >= 5)) {
  6210. $result[$format] = true;
  6211. return true;
  6212. } else {
  6213. $result[$format] = false;
  6214. return false;
  6215. }
  6216. } elseif ($format == 'mp4') {
  6217. //native mp4 support (TODO: Android, iPhone)
  6218. if ($current_browser == 'Android' || $current_browser == 'iPhone') {
  6219. $result[$format] = true;
  6220. return true;
  6221. } else {
  6222. $result[$format] = false;
  6223. return false;
  6224. }
  6225. } elseif ($format == 'mov') {
  6226. //native mov support( TODO:check iPhone)
  6227. if ($current_browser == 'Safari' && $current_majorver >= 5 || $current_browser == 'iPhone') {
  6228. $result[$format] = true;
  6229. return true;
  6230. } else {
  6231. $result[$format] = false;
  6232. return false;
  6233. }
  6234. } elseif ($format == 'avi') {
  6235. //native avi support
  6236. if ($current_browser == 'Safari' && $current_majorver >= 5) {
  6237. $result[$format] = true;
  6238. return true;
  6239. } else {
  6240. $result[$format] = false;
  6241. return false;
  6242. }
  6243. } elseif ($format == 'wmv') {
  6244. //native wmv support
  6245. if ($current_browser == 'Firefox' && $current_majorver >= 4) {
  6246. $result[$format] = true;
  6247. return true;
  6248. } else {
  6249. $result[$format] = false;
  6250. return false;
  6251. }
  6252. } elseif ($format == 'webm') {
  6253. //native webm support (TODO:check IE9, Chrome9, Android)
  6254. if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
  6255. ($current_browser == 'Opera' && $current_majorver >= 9) ||
  6256. ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
  6257. ($current_browser == 'Chrome' && $current_majorver >= 9) ||
  6258. $current_browser == 'Android'
  6259. ) {
  6260. $result[$format] = true;
  6261. return true;
  6262. } else {
  6263. $result[$format] = false;
  6264. return false;
  6265. }
  6266. } elseif ($format == 'wav') {
  6267. //native wav support (only some codecs !)
  6268. if (($current_browser == 'Firefox' && $current_majorver >= 4) ||
  6269. ($current_browser == 'Safari' && $current_majorver >= 5) ||
  6270. ($current_browser == 'Opera' && $current_majorver >= 9) ||
  6271. ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
  6272. ($current_browser == 'Chrome' && $current_majorver > 9) ||
  6273. $current_browser == 'Android' ||
  6274. $current_browser == 'iPhone'
  6275. ) {
  6276. $result[$format] = true;
  6277. return true;
  6278. } else {
  6279. $result[$format] = false;
  6280. return false;
  6281. }
  6282. } elseif ($format == 'mid' || $format == 'kar') {
  6283. //native midi support (TODO:check Android)
  6284. if ($current_browser == 'Opera' && $current_majorver >= 9 || $current_browser == 'Android') {
  6285. $result[$format] = true;
  6286. return true;
  6287. } else {
  6288. $result[$format] = false;
  6289. return false;
  6290. }
  6291. } elseif ($format == 'wma') {
  6292. //native wma support
  6293. if ($current_browser == 'Firefox' && $current_majorver >= 4) {
  6294. $result[$format] = true;
  6295. return true;
  6296. } else {
  6297. $result[$format] = false;
  6298. return false;
  6299. }
  6300. } elseif ($format == 'au') {
  6301. //native au support
  6302. if ($current_browser == 'Safari' && $current_majorver >= 5) {
  6303. $result[$format] = true;
  6304. return true;
  6305. } else {
  6306. $result[$format] = false;
  6307. return false;
  6308. }
  6309. } elseif ($format == 'mp3') {
  6310. //native mp3 support (TODO:check Android, iPhone)
  6311. if (($current_browser == 'Safari' && $current_majorver >= 5) ||
  6312. ($current_browser == 'Chrome' && $current_majorver >= 6) ||
  6313. ($current_browser == 'Internet Explorer' && $current_majorver >= 9) ||
  6314. $current_browser == 'Android' ||
  6315. $current_browser == 'iPhone' ||
  6316. $current_browser == 'Firefox'
  6317. ) {
  6318. $result[$format] = true;
  6319. return true;
  6320. } else {
  6321. $result[$format] = false;
  6322. return false;
  6323. }
  6324. } elseif ($format == 'autocapitalize') {
  6325. // Help avoiding showing the autocapitalize option if the browser doesn't
  6326. // support it: this attribute is against the HTML5 standard
  6327. if ($current_browser == 'Safari' || $current_browser == 'iPhone') {
  6328. return true;
  6329. } else {
  6330. return false;
  6331. }
  6332. } elseif ($format == "check_browser") {
  6333. $array_check_browser = [$current_browser, $current_majorver];
  6334. return $array_check_browser;
  6335. } else {
  6336. $result[$format] = false;
  6337. return false;
  6338. }
  6339. }
  6340. /**
  6341. * This function checks if exist path and file browscap.ini
  6342. * In order for this to work, your browscap configuration setting in php.ini
  6343. * must point to the correct location of the browscap.ini file on your system
  6344. * http://php.net/manual/en/function.get-browser.php.
  6345. *
  6346. * @return bool
  6347. *
  6348. * @author Juan Carlos Raña Trabado
  6349. */
  6350. function api_check_browscap()
  6351. {
  6352. $setting = ini_get('browscap');
  6353. if ($setting) {
  6354. $browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
  6355. if (strpos($setting, 'browscap.ini') && !empty($browser)) {
  6356. return true;
  6357. }
  6358. }
  6359. return false;
  6360. }
  6361. /**
  6362. * Returns the <script> HTML tag.
  6363. */
  6364. function api_get_js($file)
  6365. {
  6366. return '<script type="text/javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/'.$file.'"></script>'."\n";
  6367. }
  6368. function api_get_build_js($file)
  6369. {
  6370. return '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'build/'.$file.'"></script>'."\n";
  6371. }
  6372. /**
  6373. * Returns the <script> HTML tag.
  6374. *
  6375. * @return string
  6376. */
  6377. function api_get_asset($file)
  6378. {
  6379. return '<script type="text/javascript" src="'.api_get_path(WEB_PUBLIC_PATH).'libs/'.$file.'"></script>'."\n";
  6380. }
  6381. /**
  6382. * Returns the <script> HTML tag.
  6383. *
  6384. * @param string $file
  6385. * @param string $media
  6386. *
  6387. * @return string
  6388. */
  6389. function api_get_css_asset($file, $media = 'screen')
  6390. {
  6391. return '<link href="'.api_get_path(WEB_PUBLIC_PATH).'libs/'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
  6392. }
  6393. /**
  6394. * Returns the <link> HTML tag.
  6395. *
  6396. * @param string $file
  6397. * @param string $media
  6398. */
  6399. function api_get_css($file, $media = 'screen')
  6400. {
  6401. return '<link href="'.$file.'" rel="stylesheet" media="'.$media.'" type="text/css" />'."\n";
  6402. }
  6403. function api_get_bootstrap_and_font_awesome($returnOnlyPath = false)
  6404. {
  6405. $url = api_get_path(WEB_PUBLIC_PATH).'build/css/bootstrap.css';
  6406. if ($returnOnlyPath) {
  6407. return $url;
  6408. }
  6409. return '<link href="'.$url.'" rel="stylesheet" type="text/css" />'."\n";
  6410. }
  6411. /**
  6412. * Returns the js header to include the jquery library.
  6413. */
  6414. function api_get_jquery_js()
  6415. {
  6416. return api_get_asset('jquery/jquery.min.js');
  6417. }
  6418. /**
  6419. * Returns the jquery path.
  6420. *
  6421. * @return string
  6422. */
  6423. function api_get_jquery_web_path()
  6424. {
  6425. return api_get_path(WEB_PUBLIC_PATH).'assets/jquery/jquery.min.js';
  6426. }
  6427. /**
  6428. * @return string
  6429. */
  6430. function api_get_jquery_ui_js_web_path()
  6431. {
  6432. return api_get_path(WEB_PUBLIC_PATH).'assets/jquery-ui/jquery-ui.min.js';
  6433. }
  6434. /**
  6435. * @return string
  6436. */
  6437. function api_get_jquery_ui_css_web_path()
  6438. {
  6439. return api_get_path(WEB_PUBLIC_PATH).'assets/jquery-ui/themes/smoothness/jquery-ui.min.css';
  6440. }
  6441. /**
  6442. * Returns the jquery-ui library js headers.
  6443. *
  6444. * @return string html tags
  6445. */
  6446. function api_get_jquery_ui_js()
  6447. {
  6448. $libraries = [];
  6449. return api_get_jquery_libraries_js($libraries);
  6450. }
  6451. function api_get_jqgrid_js()
  6452. {
  6453. $routePublic = Container::getRouter()->generate('legacy_public');
  6454. return api_get_css($routePublic.'build/free-jqgrid.css').PHP_EOL
  6455. .api_get_js_simple($routePublic.'build/free-jqgrid.js');
  6456. }
  6457. /**
  6458. * Returns the jquery library js and css headers.
  6459. *
  6460. * @param array list of jquery libraries supported jquery-ui
  6461. * @param bool add the jquery library
  6462. *
  6463. * @return string html tags
  6464. */
  6465. function api_get_jquery_libraries_js($libraries)
  6466. {
  6467. $js = '';
  6468. //Document multiple upload funcionality
  6469. if (in_array('jquery-uploadzs', $libraries)) {
  6470. $js .= api_get_asset('blueimp-load-image/js/load-image.all.min.js');
  6471. $js .= api_get_asset('blueimp-canvas-to-blob/js/canvas-to-blob.min.js');
  6472. $js .= api_get_asset('jquery-file-upload/js/jquery.iframe-transport.js');
  6473. $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload.js');
  6474. $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-process.js');
  6475. $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-image.js');
  6476. $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-audio.js');
  6477. $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-video.js');
  6478. $js .= api_get_asset('jquery-file-upload/js/jquery.fileupload-validate.js');
  6479. $js .= api_get_css(api_get_path(WEB_PUBLIC_PATH).'assets/jquery-file-upload/css/jquery.fileupload.css');
  6480. $js .= api_get_css(api_get_path(WEB_PUBLIC_PATH).'assets/jquery-file-upload/css/jquery.fileupload-ui.css');
  6481. }
  6482. // jquery datepicker
  6483. if (in_array('datepicker', $libraries)) {
  6484. $languaje = 'en-GB';
  6485. $platform_isocode = strtolower(api_get_language_isocode());
  6486. $datapicker_langs = [
  6487. 'af', 'ar', 'ar-DZ', 'az', 'bg', 'bs', 'ca', 'cs', 'cy-GB', 'da', 'de', 'el', 'en-AU', 'en-GB', 'en-NZ', 'eo', 'es', 'et', 'eu', 'fa', 'fi', 'fo', 'fr', 'fr-CH', 'gl', 'he', 'hi', 'hr', 'hu', 'hy', 'id', 'is', 'it', 'ja', 'ka', 'kk', 'km', 'ko', 'lb', 'lt', 'lv', 'mk', 'ml', 'ms', 'nl', 'nl-BE', 'no', 'pl', 'pt', 'pt-BR', 'rm', 'ro', 'ru', 'sk', 'sl', 'sq', 'sr', 'sr-SR', 'sv', 'ta', 'th', 'tj', 'tr', 'uk', 'vi', 'zh-CN', 'zh-HK', 'zh-TW',
  6488. ];
  6489. if (in_array($platform_isocode, $datapicker_langs)) {
  6490. $languaje = $platform_isocode;
  6491. }
  6492. $js .= api_get_js('jquery-ui/jquery-ui-i18n.min.js');
  6493. $script = '<script>
  6494. $(function(){
  6495. $.datepicker.setDefaults($.datepicker.regional["'.$languaje.'"]);
  6496. $.datepicker.regional["local"] = $.datepicker.regional["'.$languaje.'"];
  6497. });
  6498. </script>
  6499. ';
  6500. $js .= $script;
  6501. }
  6502. return $js;
  6503. }
  6504. /**
  6505. * Returns the URL to the course or session, removing the complexity of the URL
  6506. * building piece by piece.
  6507. *
  6508. * This function relies on api_get_course_info()
  6509. *
  6510. * @param string $courseCode The course code - optional (takes it from context if not given)
  6511. * @param int $sessionId The session ID - optional (takes it from context if not given)
  6512. * @param int $groupId The group ID - optional (takes it from context if not given)
  6513. *
  6514. * @return string The URL to a course, a session, or empty string if nothing works e.g. https://localhost/courses/ABC/index.php?session_id=3&gidReq=1
  6515. *
  6516. * @author Julio Montoya <gugli100@gmail.com>
  6517. */
  6518. function api_get_course_url($courseCode = null, $sessionId = null, $groupId = null)
  6519. {
  6520. $courseDirectory = '';
  6521. $url = '';
  6522. // If courseCode not set, get context or []
  6523. if (empty($courseCode)) {
  6524. $courseInfo = api_get_course_info();
  6525. } else {
  6526. $courseInfo = api_get_course_info($courseCode);
  6527. }
  6528. // If course defined, get directory, otherwise keep empty string
  6529. if (!empty($courseInfo['directory'])) {
  6530. $courseDirectory = $courseInfo['directory'];
  6531. }
  6532. // If sessionId not set, get context or 0
  6533. if (empty($sessionId)) {
  6534. $sessionId = api_get_session_id();
  6535. }
  6536. // If groupId not set, get context or 0
  6537. if (empty($groupId)) {
  6538. $groupId = api_get_group_id();
  6539. }
  6540. // Build the URL
  6541. if (!empty($courseDirectory)) {
  6542. // directory not empty, so we do have a course
  6543. $url = api_get_path(WEB_COURSE_PATH).$courseDirectory.'/index.php?id_session='.$sessionId.'&gidReq='.$groupId;
  6544. } elseif (!empty($sessionId) &&
  6545. api_get_setting('session.remove_session_url') !== 'true'
  6546. ) {
  6547. // if the course was unset and the session was set, send directly to the session
  6548. $url = api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$sessionId;
  6549. }
  6550. // if not valid combination was found, return an empty string
  6551. return $url;
  6552. }
  6553. /**
  6554. * Check if the current portal has the $_configuration['multiple_access_urls'] parameter on.
  6555. *
  6556. * @return bool true if multi site is enabled
  6557. */
  6558. function api_get_multiple_access_url()
  6559. {
  6560. global $_configuration;
  6561. if (isset($_configuration['multiple_access_urls']) && $_configuration['multiple_access_urls']) {
  6562. return true;
  6563. }
  6564. return false;
  6565. }
  6566. /**
  6567. * @return bool
  6568. */
  6569. function api_is_multiple_url_enabled()
  6570. {
  6571. return api_get_multiple_access_url();
  6572. }
  6573. /**
  6574. * Returns a md5 unique id.
  6575. *
  6576. * @todo add more parameters
  6577. */
  6578. function api_get_unique_id()
  6579. {
  6580. $id = md5(time().uniqid().api_get_user_id().api_get_course_id().api_get_session_id());
  6581. return $id;
  6582. }
  6583. /**
  6584. * Get home path.
  6585. *
  6586. * @return string
  6587. */
  6588. function api_get_home_path()
  6589. {
  6590. // FIX : Start the routing determination from central path definition
  6591. $home = api_get_path(SYS_HOME_PATH);
  6592. if (api_get_multiple_access_url()) {
  6593. $access_url_id = api_get_current_access_url_id();
  6594. $url_info = api_get_access_url($access_url_id);
  6595. $url = api_remove_trailing_slash(preg_replace('/https?:\/\//i', '', $url_info['url']));
  6596. $clean_url = api_replace_dangerous_char($url);
  6597. $clean_url = str_replace('/', '-', $clean_url);
  6598. $clean_url .= '/';
  6599. if ($clean_url != 'localhost/') {
  6600. // means that the multiple URL was not well configured we don't rename the $home variable
  6601. return "{$home}{$clean_url}";
  6602. }
  6603. }
  6604. return $home;
  6605. }
  6606. /**
  6607. * @param int Course id
  6608. * @param int tool id: TOOL_QUIZ, TOOL_FORUM, TOOL_STUDENTPUBLICATION, TOOL_LEARNPATH
  6609. * @param int the item id (tool id, exercise id, lp id)
  6610. *
  6611. * @return bool
  6612. */
  6613. function api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code = null)
  6614. {
  6615. if (api_is_platform_admin()) {
  6616. return false;
  6617. }
  6618. if (api_get_setting('gradebook_locking_enabled') == 'true') {
  6619. if (empty($course_code)) {
  6620. $course_code = api_get_course_id();
  6621. }
  6622. $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
  6623. $item_id = intval($item_id);
  6624. $link_type = intval($link_type);
  6625. $course_code = Database::escape_string($course_code);
  6626. $sql = "SELECT locked FROM $table
  6627. WHERE locked = 1 AND ref_id = $item_id AND type = $link_type AND course_code = '$course_code' ";
  6628. $result = Database::query($sql);
  6629. if (Database::num_rows($result)) {
  6630. return true;
  6631. }
  6632. }
  6633. return false;
  6634. }
  6635. /**
  6636. * Blocks a page if the item was added in a gradebook.
  6637. *
  6638. * @param int exercise id, work id, thread id,
  6639. * @param int LINK_EXERCISE, LINK_STUDENTPUBLICATION, LINK_LEARNPATH LINK_FORUM_THREAD, LINK_ATTENDANCE
  6640. * see gradebook/lib/be/linkfactory
  6641. * @param string course code
  6642. *
  6643. * @return false|null
  6644. */
  6645. function api_block_course_item_locked_by_gradebook($item_id, $link_type, $course_code = null)
  6646. {
  6647. if (api_is_platform_admin()) {
  6648. return false;
  6649. }
  6650. if (api_resource_is_locked_by_gradebook($item_id, $link_type, $course_code)) {
  6651. $message = Display::return_message(get_lang('This option is not available because this activity is contained by an assessment, which is currently locked. To unlock the assessment, ask your platform administrator.'), 'warning');
  6652. api_not_allowed(true, $message);
  6653. }
  6654. }
  6655. /**
  6656. * Checks the PHP version installed is enough to run Chamilo.
  6657. *
  6658. * @param string Include path (used to load the error page)
  6659. */
  6660. function api_check_php_version()
  6661. {
  6662. if (!function_exists('version_compare') ||
  6663. version_compare(phpversion(), REQUIRED_PHP_VERSION, '<')
  6664. ) {
  6665. throw new Exception('Wrong PHP version');
  6666. }
  6667. }
  6668. /**
  6669. * Checks whether the Archive directory is present and writeable. If not,
  6670. * prints a warning message.
  6671. */
  6672. function api_check_archive_dir()
  6673. {
  6674. if (is_dir(api_get_path(SYS_ARCHIVE_PATH)) && !is_writable(api_get_path(SYS_ARCHIVE_PATH))) {
  6675. $message = Display::return_message(get_lang('The app/cache/ directory, used by this tool, is not writeable. Please contact your platform administrator.'), 'warning');
  6676. api_not_allowed(true, $message);
  6677. }
  6678. }
  6679. /**
  6680. * Returns an array of global configuration settings which should be ignored
  6681. * when printing the configuration settings screens.
  6682. *
  6683. * @return array Array of strings, each identifying one of the excluded settings
  6684. */
  6685. function api_get_locked_settings()
  6686. {
  6687. return [
  6688. 'permanently_remove_deleted_files',
  6689. 'account_valid_duration',
  6690. 'service_ppt2lp',
  6691. 'wcag_anysurfer_public_pages',
  6692. 'upload_extensions_list_type',
  6693. 'upload_extensions_blacklist',
  6694. 'upload_extensions_whitelist',
  6695. 'upload_extensions_skip',
  6696. 'upload_extensions_replace_by',
  6697. 'hide_dltt_markup',
  6698. 'split_users_upload_directory',
  6699. 'permissions_for_new_directories',
  6700. 'permissions_for_new_files',
  6701. 'platform_charset',
  6702. 'ldap_description',
  6703. 'cas_activate',
  6704. 'cas_server',
  6705. 'cas_server_uri',
  6706. 'cas_port',
  6707. 'cas_protocol',
  6708. 'cas_add_user_activate',
  6709. 'update_user_info_cas_with_ldap',
  6710. 'languagePriority1',
  6711. 'languagePriority2',
  6712. 'languagePriority3',
  6713. 'languagePriority4',
  6714. 'login_is_email',
  6715. 'chamilo_database_version',
  6716. ];
  6717. }
  6718. /**
  6719. * Checks if the user is corrently logged in. Returns the user ID if he is, or
  6720. * false if he isn't. If the user ID is given and is an integer, then the same
  6721. * ID is simply returned.
  6722. *
  6723. * @param int User ID
  6724. *
  6725. * @return bool Integer User ID is logged in, or false otherwise
  6726. */
  6727. function api_user_is_login($user_id = null)
  6728. {
  6729. return Container::getAuthorizationChecker()->isGranted('IS_AUTHENTICATED_FULLY');
  6730. }
  6731. /**
  6732. * Guess the real ip for register in the database, even in reverse proxy cases.
  6733. * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
  6734. * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
  6735. * Note: the result of this function is not SQL-safe. Please escape it before
  6736. * inserting in a database.
  6737. *
  6738. * @return string the user's real ip (unsafe - escape it before inserting to db)
  6739. *
  6740. * @author Jorge Frisancho Jibaja <jrfdeft@gmail.com>, USIL - Some changes to allow the use of real IP using reverse proxy
  6741. *
  6742. * @version CEV CHANGE 24APR2012
  6743. */
  6744. function api_get_real_ip()
  6745. {
  6746. $ip = trim($_SERVER['REMOTE_ADDR']);
  6747. if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  6748. if (preg_match('/,/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
  6749. @list($ip1, $ip2) = @explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  6750. } else {
  6751. $ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
  6752. }
  6753. $ip = trim($ip1);
  6754. }
  6755. return $ip;
  6756. }
  6757. /**
  6758. * Checks whether an IP is included inside an IP range.
  6759. *
  6760. * @param string IP address
  6761. * @param string IP range
  6762. * @param string $ip
  6763. *
  6764. * @return bool True if IP is in the range, false otherwise
  6765. *
  6766. * @author claudiu at cnixs dot com on http://www.php.net/manual/fr/ref.network.php#55230
  6767. * @author Yannick Warnier for improvements and managment of multiple ranges
  6768. *
  6769. * @todo check for IPv6 support
  6770. */
  6771. function api_check_ip_in_range($ip, $range)
  6772. {
  6773. if (empty($ip) or empty($range)) {
  6774. return false;
  6775. }
  6776. $ip_ip = ip2long($ip);
  6777. // divide range param into array of elements
  6778. if (strpos($range, ',') !== false) {
  6779. $ranges = explode(',', $range);
  6780. } else {
  6781. $ranges = [$range];
  6782. }
  6783. foreach ($ranges as $range) {
  6784. $range = trim($range);
  6785. if (empty($range)) {
  6786. continue;
  6787. }
  6788. if (strpos($range, '/') === false) {
  6789. if (strcmp($ip, $range) === 0) {
  6790. return true; // there is a direct IP match, return OK
  6791. }
  6792. continue; //otherwise, get to the next range
  6793. }
  6794. // the range contains a "/", so analyse completely
  6795. list($net, $mask) = explode("/", $range);
  6796. $ip_net = ip2long($net);
  6797. // mask binary magic
  6798. $ip_mask = ~((1 << (32 - $mask)) - 1);
  6799. $ip_ip_net = $ip_ip & $ip_mask;
  6800. if ($ip_ip_net == $ip_net) {
  6801. return true;
  6802. }
  6803. }
  6804. return false;
  6805. }
  6806. function api_check_user_access_to_legal($course_visibility)
  6807. {
  6808. $course_visibility_list = [COURSE_VISIBILITY_OPEN_WORLD, COURSE_VISIBILITY_OPEN_PLATFORM];
  6809. return in_array($course_visibility, $course_visibility_list) || api_is_drh();
  6810. }
  6811. /**
  6812. * Checks if the global chat is enabled or not.
  6813. *
  6814. * @return bool
  6815. */
  6816. function api_is_global_chat_enabled()
  6817. {
  6818. return
  6819. !api_is_anonymous() &&
  6820. api_get_setting('allow_global_chat') === 'true' &&
  6821. api_get_setting('allow_social_tool') === 'true';
  6822. }
  6823. /**
  6824. * @todo Fix tool_visible_by_default_at_creation labels
  6825. * @todo Add sessionId parameter to avoid using context
  6826. *
  6827. * @param int $item_id
  6828. * @param int $tool_id
  6829. * @param int $group_id id
  6830. * @param array $courseInfo
  6831. * @param int $sessionId
  6832. * @param int $userId
  6833. */
  6834. function api_set_default_visibility(
  6835. $item_id,
  6836. $tool_id,
  6837. $group_id = 0,
  6838. $courseInfo = [],
  6839. $sessionId = 0,
  6840. $userId = 0
  6841. ) {
  6842. $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
  6843. $courseId = $courseInfo['real_id'];
  6844. $courseCode = $courseInfo['code'];
  6845. $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
  6846. $userId = empty($userId) ? api_get_user_id() : $userId;
  6847. // if group is null force group_id = 0, this force is needed to create a LP folder with group = 0
  6848. if (is_null($group_id)) {
  6849. $group_id = 0;
  6850. } else {
  6851. $group_id = empty($group_id) ? api_get_group_id() : $group_id;
  6852. }
  6853. $groupInfo = [];
  6854. if (!empty($group_id)) {
  6855. $groupInfo = GroupManager::get_group_properties($group_id);
  6856. }
  6857. $original_tool_id = $tool_id;
  6858. switch ($tool_id) {
  6859. case TOOL_LINK:
  6860. case TOOL_LINK_CATEGORY:
  6861. $tool_id = 'links';
  6862. break;
  6863. case TOOL_DOCUMENT:
  6864. $tool_id = 'documents';
  6865. break;
  6866. case TOOL_LEARNPATH:
  6867. $tool_id = 'learning';
  6868. break;
  6869. case TOOL_ANNOUNCEMENT:
  6870. $tool_id = 'announcements';
  6871. break;
  6872. case TOOL_FORUM:
  6873. case TOOL_FORUM_CATEGORY:
  6874. case TOOL_FORUM_THREAD:
  6875. $tool_id = 'forums';
  6876. break;
  6877. case TOOL_QUIZ:
  6878. $tool_id = 'quiz';
  6879. break;
  6880. }
  6881. $setting = api_get_setting('tool_visible_by_default_at_creation');
  6882. if (isset($setting[$tool_id])) {
  6883. $visibility = 'invisible';
  6884. if ($setting[$tool_id] == 'true') {
  6885. $visibility = 'visible';
  6886. }
  6887. // Read the portal and course default visibility
  6888. if ($tool_id === 'documents') {
  6889. $visibility = DocumentManager::getDocumentDefaultVisibility($courseInfo);
  6890. }
  6891. api_item_property_update(
  6892. $courseInfo,
  6893. $original_tool_id,
  6894. $item_id,
  6895. $visibility,
  6896. $userId,
  6897. $groupInfo,
  6898. null,
  6899. null,
  6900. null,
  6901. $sessionId
  6902. );
  6903. // Fixes default visibility for tests
  6904. switch ($original_tool_id) {
  6905. case TOOL_QUIZ:
  6906. if (empty($sessionId)) {
  6907. $objExerciseTmp = new Exercise($courseId);
  6908. $objExerciseTmp->read($item_id);
  6909. if ($visibility == 'visible') {
  6910. $objExerciseTmp->enable();
  6911. $objExerciseTmp->save();
  6912. } else {
  6913. $objExerciseTmp->disable();
  6914. $objExerciseTmp->save();
  6915. }
  6916. }
  6917. break;
  6918. }
  6919. }
  6920. }
  6921. /**
  6922. * @return string
  6923. */
  6924. function api_get_security_key()
  6925. {
  6926. return api_get_configuration_value('security_key');
  6927. }
  6928. /**
  6929. * @param int $user_id
  6930. * @param int $courseId
  6931. * @param int $session_id
  6932. *
  6933. * @return array
  6934. */
  6935. function api_detect_user_roles($user_id, $courseId, $session_id = 0)
  6936. {
  6937. $user_roles = [];
  6938. $courseInfo = api_get_course_info_by_id($courseId);
  6939. $course_code = $courseInfo['code'];
  6940. $url_id = api_get_current_access_url_id();
  6941. if (api_is_platform_admin_by_id($user_id, $url_id)) {
  6942. $user_roles[] = PLATFORM_ADMIN;
  6943. }
  6944. /*if (api_is_drh()) {
  6945. $user_roles[] = DRH;
  6946. }*/
  6947. if (!empty($session_id)) {
  6948. if (SessionManager::user_is_general_coach($user_id, $session_id)) {
  6949. $user_roles[] = SESSION_GENERAL_COACH;
  6950. }
  6951. }
  6952. if (!empty($course_code)) {
  6953. if (empty($session_id)) {
  6954. if (CourseManager::is_course_teacher($user_id, $course_code)) {
  6955. $user_roles[] = COURSEMANAGER;
  6956. }
  6957. if (CourseManager::get_tutor_in_course_status($user_id, $courseInfo['real_id'])) {
  6958. $user_roles[] = COURSE_TUTOR;
  6959. }
  6960. if (CourseManager::is_user_subscribed_in_course($user_id, $course_code)) {
  6961. $user_roles[] = COURSE_STUDENT;
  6962. }
  6963. } else {
  6964. $user_status_in_session = SessionManager::get_user_status_in_course_session(
  6965. $user_id,
  6966. $courseId,
  6967. $session_id
  6968. );
  6969. if (!empty($user_status_in_session)) {
  6970. if ($user_status_in_session == 0) {
  6971. $user_roles[] = SESSION_STUDENT;
  6972. }
  6973. if ($user_status_in_session == 2) {
  6974. $user_roles[] = SESSION_COURSE_COACH;
  6975. }
  6976. }
  6977. /*if (api_is_course_session_coach($user_id, $course_code, $session_id)) {
  6978. $user_roles[] = SESSION_COURSE_COACH;
  6979. }*/
  6980. }
  6981. }
  6982. return $user_roles;
  6983. }
  6984. /**
  6985. * @param int $courseId
  6986. * @param int $session_id
  6987. *
  6988. * @return bool
  6989. */
  6990. function api_coach_can_edit_view_results($courseId = null, $session_id = null)
  6991. {
  6992. if (api_is_platform_admin()) {
  6993. return true;
  6994. }
  6995. $user_id = api_get_user_id();
  6996. if (empty($courseId)) {
  6997. $courseId = api_get_course_int_id();
  6998. }
  6999. if (empty($session_id)) {
  7000. $session_id = api_get_session_id();
  7001. }
  7002. $roles = api_detect_user_roles($user_id, $courseId, $session_id);
  7003. if (in_array(SESSION_COURSE_COACH, $roles)) {
  7004. //return api_get_setting('session_tutor_reports_visibility') == 'true';
  7005. return true;
  7006. } else {
  7007. if (in_array(COURSEMANAGER, $roles)) {
  7008. return true;
  7009. }
  7010. return false;
  7011. }
  7012. }
  7013. /**
  7014. * @param string $file
  7015. *
  7016. * @return string
  7017. */
  7018. function api_get_js_simple($file)
  7019. {
  7020. return '<script type="text/javascript" src="'.$file.'"></script>'."\n";
  7021. }
  7022. function api_set_settings_and_plugins()
  7023. {
  7024. global $_configuration;
  7025. $_setting = [];
  7026. $_plugins = [];
  7027. // access_url == 1 is the default chamilo location
  7028. $settings_by_access_list = [];
  7029. $access_url_id = api_get_current_access_url_id();
  7030. if ($access_url_id != 1) {
  7031. $url_info = api_get_access_url($_configuration['access_url']);
  7032. if ($url_info['active'] == 1) {
  7033. $settings_by_access = &api_get_settings(null, 'list', $_configuration['access_url'], 1);
  7034. foreach ($settings_by_access as &$row) {
  7035. if (empty($row['variable'])) {
  7036. $row['variable'] = 0;
  7037. }
  7038. if (empty($row['subkey'])) {
  7039. $row['subkey'] = 0;
  7040. }
  7041. if (empty($row['category'])) {
  7042. $row['category'] = 0;
  7043. }
  7044. $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
  7045. }
  7046. }
  7047. }
  7048. $result = api_get_settings(null, 'list', 1);
  7049. foreach ($result as &$row) {
  7050. if ($access_url_id != 1) {
  7051. if ($url_info['active'] == 1) {
  7052. $var = empty($row['variable']) ? 0 : $row['variable'];
  7053. $subkey = empty($row['subkey']) ? 0 : $row['subkey'];
  7054. $category = empty($row['category']) ? 0 : $row['category'];
  7055. }
  7056. if ($row['access_url_changeable'] == 1 && $url_info['active'] == 1) {
  7057. if (isset($settings_by_access_list[$var]) &&
  7058. $settings_by_access_list[$var][$subkey][$category]['selected_value'] != '') {
  7059. if ($row['subkey'] == null) {
  7060. $_setting[$row['variable']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
  7061. } else {
  7062. $_setting[$row['variable']][$row['subkey']] = $settings_by_access_list[$var][$subkey][$category]['selected_value'];
  7063. }
  7064. } else {
  7065. if ($row['subkey'] == null) {
  7066. $_setting[$row['variable']] = $row['selected_value'];
  7067. } else {
  7068. $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
  7069. }
  7070. }
  7071. } else {
  7072. if ($row['subkey'] == null) {
  7073. $_setting[$row['variable']] = $row['selected_value'];
  7074. } else {
  7075. $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
  7076. }
  7077. }
  7078. } else {
  7079. if ($row['subkey'] == null) {
  7080. $_setting[$row['variable']] = $row['selected_value'];
  7081. } else {
  7082. $_setting[$row['variable']][$row['subkey']] = $row['selected_value'];
  7083. }
  7084. }
  7085. }
  7086. $result = api_get_settings('Plugins', 'list', $access_url_id);
  7087. $_plugins = [];
  7088. foreach ($result as &$row) {
  7089. $key = &$row['variable'];
  7090. if (is_string($_setting[$key])) {
  7091. $_setting[$key] = [];
  7092. }
  7093. $_setting[$key][] = $row['selected_value'];
  7094. $_plugins[$key][] = $row['selected_value'];
  7095. }
  7096. $_SESSION['_setting'] = $_setting;
  7097. $_SESSION['_plugins'] = $_plugins;
  7098. }
  7099. /**
  7100. * Modify default memory_limit and max_execution_time limits
  7101. * Needed when processing long tasks.
  7102. */
  7103. function api_set_more_memory_and_time_limits()
  7104. {
  7105. if (function_exists('ini_set')) {
  7106. api_set_memory_limit('256M');
  7107. ini_set('max_execution_time', 1800);
  7108. }
  7109. }
  7110. /**
  7111. * Tries to set memory limit, if authorized and new limit is higher than current.
  7112. *
  7113. * @param string $mem New memory limit
  7114. *
  7115. * @return bool True on success, false on failure or current is higher than suggested
  7116. * @assert (null) === false
  7117. * @assert (-1) === false
  7118. * @assert (0) === true
  7119. * @assert ('1G') === true
  7120. */
  7121. function api_set_memory_limit($mem)
  7122. {
  7123. //if ini_set() not available, this function is useless
  7124. if (!function_exists('ini_set') || is_null($mem) || $mem == -1) {
  7125. return false;
  7126. }
  7127. $memory_limit = ini_get('memory_limit');
  7128. if (api_get_bytes_memory_limit($mem) > api_get_bytes_memory_limit($memory_limit)) {
  7129. ini_set('memory_limit', $mem);
  7130. return true;
  7131. }
  7132. return false;
  7133. }
  7134. /**
  7135. * Gets memory limit in bytes.
  7136. *
  7137. * @param string The memory size (128M, 1G, 1000K, etc)
  7138. *
  7139. * @return int
  7140. * @assert (null) === false
  7141. * @assert ('1t') === 1099511627776
  7142. * @assert ('1g') === 1073741824
  7143. * @assert ('1m') === 1048576
  7144. * @assert ('100k') === 102400
  7145. */
  7146. function api_get_bytes_memory_limit($mem)
  7147. {
  7148. $size = strtolower(substr($mem, -1));
  7149. switch ($size) {
  7150. case 't':
  7151. $mem = intval(substr($mem, -1)) * 1024 * 1024 * 1024 * 1024;
  7152. break;
  7153. case 'g':
  7154. $mem = intval(substr($mem, 0, -1)) * 1024 * 1024 * 1024;
  7155. break;
  7156. case 'm':
  7157. $mem = intval(substr($mem, 0, -1)) * 1024 * 1024;
  7158. break;
  7159. case 'k':
  7160. $mem = intval(substr($mem, 0, -1)) * 1024;
  7161. break;
  7162. default:
  7163. // we assume it's integer only
  7164. $mem = intval($mem);
  7165. break;
  7166. }
  7167. return $mem;
  7168. }
  7169. /**
  7170. * Finds all the information about a user from username instead of user id.
  7171. *
  7172. * @param string $officialCode
  7173. *
  7174. * @return array $user_info user_id, lastname, firstname, username, email, ...
  7175. *
  7176. * @author Yannick Warnier <yannick.warnier@beeznest.com>
  7177. */
  7178. function api_get_user_info_from_official_code($officialCode)
  7179. {
  7180. if (empty($officialCode)) {
  7181. return false;
  7182. }
  7183. $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_USER)."
  7184. WHERE official_code ='".Database::escape_string($officialCode)."'";
  7185. $result = Database::query($sql);
  7186. if (Database::num_rows($result) > 0) {
  7187. $result_array = Database::fetch_array($result);
  7188. return _api_format_user($result_array);
  7189. }
  7190. return false;
  7191. }
  7192. /**
  7193. * @param string $usernameInputId
  7194. * @param string $passwordInputId
  7195. *
  7196. * @return string|null
  7197. */
  7198. function api_get_password_checker_js($usernameInputId, $passwordInputId)
  7199. {
  7200. $checkPass = api_get_setting('allow_strength_pass_checker');
  7201. $useStrengthPassChecker = $checkPass === 'true';
  7202. if ($useStrengthPassChecker === false) {
  7203. return null;
  7204. }
  7205. $translations = [
  7206. 'wordLength' => get_lang('The password is too short'),
  7207. 'wordNotEmail' => get_lang('Your password cannot be the same as your email'),
  7208. 'wordSimilarToUsername' => get_lang('Your password cannot contain your username'),
  7209. 'wordTwoCharacterClasses' => get_lang('Use different character classes'),
  7210. 'wordRepetitions' => get_lang('Too many repetitions'),
  7211. 'wordSequences' => get_lang('Your password contains sequences'),
  7212. 'errorList' => get_lang('errors found'),
  7213. 'veryWeak' => get_lang('Very weak'),
  7214. 'weak' => get_lang('Weak'),
  7215. 'normal' => get_lang('Normal'),
  7216. 'medium' => get_lang('Medium'),
  7217. 'strong' => get_lang('Strong'),
  7218. 'veryStrong' => get_lang('Very strong'),
  7219. ];
  7220. $js = api_get_asset('pwstrength-bootstrap/dist/pwstrength-bootstrap.min.js');
  7221. $js .= "<script>
  7222. var errorMessages = {
  7223. password_to_short : \"".get_lang('The password is too short')."\",
  7224. same_as_username : \"".get_lang('Your password cannot be the same as your username')."\"
  7225. };
  7226. $(function() {
  7227. var lang = ".json_encode($translations).";
  7228. var options = {
  7229. onLoad : function () {
  7230. //$('#messages').text('Start typing password');
  7231. },
  7232. onKeyUp: function (evt) {
  7233. $(evt.target).pwstrength('outputErrorList');
  7234. },
  7235. errorMessages : errorMessages,
  7236. viewports: {
  7237. progress: '#password_progress',
  7238. verdict: '#password-verdict',
  7239. errors: '#password-errors'
  7240. },
  7241. usernameField: '$usernameInputId'
  7242. };
  7243. options.i18n = {
  7244. t: function (key) {
  7245. var result = lang[key];
  7246. return result === key ? '' : result; // This assumes you return the
  7247. }
  7248. };
  7249. $('".$passwordInputId."').pwstrength(options);
  7250. });
  7251. </script>";
  7252. return $js;
  7253. }
  7254. /**
  7255. * create an user extra field called 'captcha_blocked_until_date'.
  7256. *
  7257. * @param string $username
  7258. *
  7259. * @return bool
  7260. */
  7261. function api_block_account_captcha($username)
  7262. {
  7263. $userInfo = api_get_user_info_from_username($username);
  7264. if (empty($userInfo)) {
  7265. return false;
  7266. }
  7267. $minutesToBlock = api_get_setting('captcha_time_to_block');
  7268. $time = time() + $minutesToBlock * 60;
  7269. UserManager::update_extra_field_value(
  7270. $userInfo['user_id'],
  7271. 'captcha_blocked_until_date',
  7272. api_get_utc_datetime($time)
  7273. );
  7274. return true;
  7275. }
  7276. /**
  7277. * @param string $username
  7278. *
  7279. * @return bool
  7280. */
  7281. function api_clean_account_captcha($username)
  7282. {
  7283. $userInfo = api_get_user_info_from_username($username);
  7284. if (empty($userInfo)) {
  7285. return false;
  7286. }
  7287. Session::erase('loginFailedCount');
  7288. UserManager::update_extra_field_value(
  7289. $userInfo['user_id'],
  7290. 'captcha_blocked_until_date',
  7291. null
  7292. );
  7293. return true;
  7294. }
  7295. /**
  7296. * @param string $username
  7297. *
  7298. * @return bool
  7299. */
  7300. function api_get_user_blocked_by_captcha($username)
  7301. {
  7302. $userInfo = api_get_user_info_from_username($username);
  7303. if (empty($userInfo)) {
  7304. return false;
  7305. }
  7306. $data = UserManager::get_extra_user_data_by_field(
  7307. $userInfo['user_id'],
  7308. 'captcha_blocked_until_date'
  7309. );
  7310. if (isset($data) && isset($data['captcha_blocked_until_date'])) {
  7311. return $data['captcha_blocked_until_date'];
  7312. }
  7313. return false;
  7314. }
  7315. /**
  7316. * Remove tags from HTML anf return the $in_number_char first non-HTML char
  7317. * Postfix the text with "..." if it has been truncated.
  7318. *
  7319. * @param string $text
  7320. * @param int $number
  7321. *
  7322. * @return string
  7323. *
  7324. * @author hubert borderiou
  7325. */
  7326. function api_get_short_text_from_html($text, $number)
  7327. {
  7328. // Delete script and style tags
  7329. $text = preg_replace('/(<(script|style)\b[^>]*>).*?(<\/\2>)/is', "$1$3", $text);
  7330. $text = api_html_entity_decode($text);
  7331. $out_res = api_remove_tags_with_space($text, false);
  7332. $postfix = "...";
  7333. if (strlen($out_res) > $number) {
  7334. $out_res = substr($out_res, 0, $number).$postfix;
  7335. }
  7336. return $out_res;
  7337. }
  7338. /**
  7339. * Replace tags with a space in a text.
  7340. * If $in_double_quote_replace, replace " with '' (for HTML attribute purpose, for exemple).
  7341. *
  7342. * @return string
  7343. *
  7344. * @author hubert borderiou
  7345. */
  7346. function api_remove_tags_with_space($in_html, $in_double_quote_replace = true)
  7347. {
  7348. $out_res = $in_html;
  7349. if ($in_double_quote_replace) {
  7350. $out_res = str_replace('"', "''", $out_res);
  7351. }
  7352. // avoid text stuck together when tags are removed, adding a space after >
  7353. $out_res = str_replace(">", "> ", $out_res);
  7354. $out_res = strip_tags($out_res);
  7355. return $out_res;
  7356. }
  7357. /**
  7358. * If true, the drh can access all content (courses, users) inside a session.
  7359. *
  7360. * @return bool
  7361. */
  7362. function api_drh_can_access_all_session_content()
  7363. {
  7364. $value = api_get_setting('drh_can_access_all_session_content');
  7365. return $value === 'true';
  7366. }
  7367. /**
  7368. * @param string $tool
  7369. * @param string $setting
  7370. * @param int $defaultValue
  7371. *
  7372. * @return string
  7373. */
  7374. function api_get_default_tool_setting($tool, $setting, $defaultValue)
  7375. {
  7376. global $_configuration;
  7377. if (isset($_configuration[$tool]) &&
  7378. isset($_configuration[$tool]['default_settings']) &&
  7379. isset($_configuration[$tool]['default_settings'][$setting])
  7380. ) {
  7381. return $_configuration[$tool]['default_settings'][$setting];
  7382. }
  7383. return $defaultValue;
  7384. }
  7385. /**
  7386. * Checks if user can login as another user.
  7387. *
  7388. * @param int $loginAsUserId the user id to log in
  7389. * @param int $userId my user id
  7390. *
  7391. * @return bool
  7392. */
  7393. function api_can_login_as($loginAsUserId, $userId = null)
  7394. {
  7395. if (empty($userId)) {
  7396. $userId = api_get_user_id();
  7397. }
  7398. if ($loginAsUserId == $userId) {
  7399. return false;
  7400. }
  7401. if (empty($loginAsUserId)) {
  7402. return false;
  7403. }
  7404. if ($loginAsUserId != strval(intval($loginAsUserId))) {
  7405. return false;
  7406. }
  7407. // Check if the user to login is an admin
  7408. if (api_is_platform_admin_by_id($loginAsUserId)) {
  7409. // Only super admins can login to admin accounts
  7410. if (!api_global_admin_can_edit_admin($loginAsUserId)) {
  7411. return false;
  7412. }
  7413. }
  7414. $userInfo = api_get_user_info($loginAsUserId);
  7415. $isDrh = function () use ($loginAsUserId) {
  7416. if (api_is_drh()) {
  7417. if (api_drh_can_access_all_session_content()) {
  7418. $users = SessionManager::getAllUsersFromCoursesFromAllSessionFromStatus(
  7419. 'drh_all',
  7420. api_get_user_id()
  7421. );
  7422. $userList = [];
  7423. if (is_array($users)) {
  7424. foreach ($users as $user) {
  7425. $userList[] = $user['user_id'];
  7426. }
  7427. }
  7428. if (in_array($loginAsUserId, $userList)) {
  7429. return true;
  7430. }
  7431. } else {
  7432. if (api_is_drh() &&
  7433. UserManager::is_user_followed_by_drh($loginAsUserId, api_get_user_id())
  7434. ) {
  7435. return true;
  7436. }
  7437. }
  7438. }
  7439. return false;
  7440. };
  7441. $loginAsStatusForSessionAdmins = [STUDENT];
  7442. if (api_get_setting('session.allow_session_admin_login_as_teacher')) {
  7443. $loginAsStatusForSessionAdmins[] = COURSEMANAGER;
  7444. }
  7445. return api_is_platform_admin() ||
  7446. (api_is_session_admin() && in_array($userInfo['status'], $loginAsStatusForSessionAdmins)) ||
  7447. $isDrh();
  7448. }
  7449. /**
  7450. * @return bool
  7451. */
  7452. function api_is_allowed_in_course()
  7453. {
  7454. if (api_is_platform_admin()) {
  7455. return true;
  7456. }
  7457. $user = api_get_current_user();
  7458. if ($user instanceof User) {
  7459. if ($user->hasRole('ROLE_CURRENT_SESSION_COURSE_STUDENT') ||
  7460. $user->hasRole('ROLE_CURRENT_SESSION_COURSE_TEACHER') ||
  7461. $user->hasRole('ROLE_CURRENT_COURSE_STUDENT') ||
  7462. $user->hasRole('ROLE_CURRENT_COURSE_TEACHER')
  7463. ) {
  7464. return true;
  7465. }
  7466. }
  7467. return false;
  7468. }
  7469. /**
  7470. * Set the cookie to go directly to the course code $in_firstpage
  7471. * after login.
  7472. *
  7473. * @param string $value is the course code of the course to go
  7474. */
  7475. function api_set_firstpage_parameter($value)
  7476. {
  7477. setcookie('GotoCourse', $value);
  7478. }
  7479. /**
  7480. * Delete the cookie to go directly to the course code $in_firstpage
  7481. * after login.
  7482. */
  7483. function api_delete_firstpage_parameter()
  7484. {
  7485. setcookie('GotoCourse', '', time() - 3600);
  7486. }
  7487. /**
  7488. * @return bool if course_code for direct course access after login is set
  7489. */
  7490. function exist_firstpage_parameter()
  7491. {
  7492. return isset($_COOKIE['GotoCourse']) && $_COOKIE['GotoCourse'] != '';
  7493. }
  7494. /**
  7495. * @return return the course_code of the course where user login
  7496. */
  7497. function api_get_firstpage_parameter()
  7498. {
  7499. return $_COOKIE['GotoCourse'];
  7500. }
  7501. /**
  7502. * Return true on https install.
  7503. *
  7504. * @return bool
  7505. */
  7506. function api_is_https()
  7507. {
  7508. if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
  7509. $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_configuration['force_https_forwarded_proto'])
  7510. ) {
  7511. $isSecured = true;
  7512. } else {
  7513. if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
  7514. $isSecured = true;
  7515. } else {
  7516. $isSecured = false;
  7517. // last chance
  7518. if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) {
  7519. $isSecured = true;
  7520. }
  7521. }
  7522. }
  7523. return $isSecured;
  7524. }
  7525. /**
  7526. * Return protocol (http or https).
  7527. *
  7528. * @return string
  7529. */
  7530. function api_get_protocol()
  7531. {
  7532. return api_is_https() ? 'https' : 'http';
  7533. }
  7534. /**
  7535. * Return a string where " are replaced with 2 '
  7536. * It is useful when you pass a PHP variable in a Javascript browser dialog
  7537. * e.g. : alert("<?php get_lang('Message') ?>");
  7538. * and message contains character ".
  7539. *
  7540. * @param string $in_text
  7541. *
  7542. * @return string
  7543. */
  7544. function convert_double_quote_to_single($in_text)
  7545. {
  7546. return api_preg_replace('/"/', "''", $in_text);
  7547. }
  7548. /**
  7549. * Get origin.
  7550. *
  7551. * @param string
  7552. *
  7553. * @return string
  7554. */
  7555. function api_get_origin()
  7556. {
  7557. $origin = isset($_REQUEST['origin']) ? Security::remove_XSS($_REQUEST['origin']) : '';
  7558. return $origin;
  7559. }
  7560. /**
  7561. * Warns an user that the portal reach certain limit.
  7562. *
  7563. * @param string $limitName
  7564. */
  7565. function api_warn_hosting_contact($limitName)
  7566. {
  7567. $hostingParams = api_get_configuration_value(1);
  7568. $email = null;
  7569. if (!empty($hostingParams)) {
  7570. if (isset($hostingParams['hosting_contact_mail'])) {
  7571. $email = $hostingParams['hosting_contact_mail'];
  7572. }
  7573. }
  7574. if (!empty($email)) {
  7575. $subject = get_lang('Hosting warning reached');
  7576. $body = get_lang('Portal name').': '.api_get_path(WEB_PATH)." \n ";
  7577. $body .= get_lang('Portal\'s limit type').': '.$limitName." \n ";
  7578. if (isset($hostingParams[$limitName])) {
  7579. $body .= get_lang('Value').': '.$hostingParams[$limitName];
  7580. }
  7581. api_mail_html(null, $email, $subject, $body);
  7582. }
  7583. }
  7584. /**
  7585. * Gets value of a variable from config/configuration.php
  7586. * Variables that are not set in the configuration.php file but set elsewhere:
  7587. * - virtual_css_theme_folder (vchamilo plugin)
  7588. * - access_url (global.inc.php)
  7589. * - apc/apc_prefix (global.inc.php).
  7590. *
  7591. * @param string $variable
  7592. *
  7593. * @return bool|mixed
  7594. */
  7595. function api_get_configuration_value($variable)
  7596. {
  7597. global $_configuration;
  7598. // Check the current url id, id = 1 by default
  7599. $urlId = isset($_configuration['access_url']) ? (int) $_configuration['access_url'] : 1;
  7600. $variable = trim($variable);
  7601. // Check if variable exists
  7602. if (isset($_configuration[$variable])) {
  7603. if (is_array($_configuration[$variable])) {
  7604. // Check if it exists for the sub portal
  7605. if (array_key_exists($urlId, $_configuration[$variable])) {
  7606. return $_configuration[$variable][$urlId];
  7607. } else {
  7608. // Try to found element with id = 1 (master portal)
  7609. if (array_key_exists(1, $_configuration[$variable])) {
  7610. return $_configuration[$variable][1];
  7611. }
  7612. }
  7613. }
  7614. return $_configuration[$variable];
  7615. }
  7616. return false;
  7617. }
  7618. /**
  7619. * Returns supported image extensions in the portal.
  7620. *
  7621. * @param bool $supportVectors Whether vector images should also be accepted or not
  7622. *
  7623. * @return array Supported image extensions in the portal
  7624. */
  7625. function api_get_supported_image_extensions($supportVectors = true)
  7626. {
  7627. // jpg can also be called jpeg, jpe, jfif and jif. See https://en.wikipedia.org/wiki/JPEG#JPEG_filename_extensions
  7628. $supportedImageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'jpe', 'jfif', 'jif'];
  7629. if ($supportVectors) {
  7630. array_push($supportedImageExtensions, 'svg');
  7631. }
  7632. if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
  7633. array_push($supportedImageExtensions, 'webp');
  7634. }
  7635. return $supportedImageExtensions;
  7636. }
  7637. /**
  7638. * This setting changes the registration status for the campus.
  7639. *
  7640. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  7641. *
  7642. * @version August 2006
  7643. *
  7644. * @param bool $listCampus Whether we authorize
  7645. *
  7646. * @todo the $_settings should be reloaded here. => write api function for this and use this in global.inc.php also.
  7647. */
  7648. function api_register_campus($listCampus = true)
  7649. {
  7650. $tbl_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  7651. $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='registered'";
  7652. Database::query($sql);
  7653. if (!$listCampus) {
  7654. $sql = "UPDATE $tbl_settings SET selected_value='true' WHERE variable='donotlistcampus'";
  7655. Database::query($sql);
  7656. }
  7657. }
  7658. /**
  7659. * Checks whether current user is a student boss.
  7660. *
  7661. * @global array $_user
  7662. *
  7663. * @return bool
  7664. */
  7665. function api_is_student_boss()
  7666. {
  7667. $_user = api_get_user_info();
  7668. return isset($_user['status']) && $_user['status'] == STUDENT_BOSS;
  7669. }
  7670. /**
  7671. * Check whether the user type should be exclude.
  7672. * Such as invited or anonymous users.
  7673. *
  7674. * @param bool $checkDB Optional. Whether check the user status
  7675. * @param int $userId Options. The user id
  7676. *
  7677. * @return bool
  7678. */
  7679. function api_is_excluded_user_type($checkDB = false, $userId = 0)
  7680. {
  7681. if ($checkDB) {
  7682. $userId = empty($userId) ? api_get_user_id() : (int) $userId;
  7683. if ($userId == 0) {
  7684. return true;
  7685. }
  7686. $userInfo = api_get_user_info($userId);
  7687. switch ($userInfo['status']) {
  7688. case INVITEE:
  7689. case ANONYMOUS:
  7690. return true;
  7691. default:
  7692. return false;
  7693. }
  7694. }
  7695. $isInvited = api_is_invitee();
  7696. $isAnonymous = api_is_anonymous();
  7697. if ($isInvited || $isAnonymous) {
  7698. return true;
  7699. }
  7700. return false;
  7701. }
  7702. /**
  7703. * Get the user status to ignore in reports.
  7704. *
  7705. * @param string $format Optional. The result type (array or string)
  7706. *
  7707. * @return array|string
  7708. */
  7709. function api_get_users_status_ignored_in_reports($format = 'array')
  7710. {
  7711. $excludedTypes = [
  7712. INVITEE,
  7713. ANONYMOUS,
  7714. ];
  7715. if ($format == 'string') {
  7716. return implode(', ', $excludedTypes);
  7717. }
  7718. return $excludedTypes;
  7719. }
  7720. /**
  7721. * Set the Site Use Cookie Warning for 1 year.
  7722. */
  7723. function api_set_site_use_cookie_warning_cookie()
  7724. {
  7725. setcookie('ChamiloUsesCookies', 'ok', time() + 31556926);
  7726. }
  7727. /**
  7728. * Return true if the Site Use Cookie Warning Cookie warning exists.
  7729. *
  7730. * @return bool
  7731. */
  7732. function api_site_use_cookie_warning_cookie_exist()
  7733. {
  7734. return isset($_COOKIE['ChamiloUsesCookies']);
  7735. }
  7736. /**
  7737. * Given a number of seconds, format the time to show hours, minutes and seconds.
  7738. *
  7739. * @param int $time The time in seconds
  7740. * @param string $originFormat Optional. PHP o JS
  7741. *
  7742. * @return string (00h00'00")
  7743. */
  7744. function api_format_time($time, $originFormat = 'php')
  7745. {
  7746. $h = get_lang('h');
  7747. $hours = $time / 3600;
  7748. $mins = ($time % 3600) / 60;
  7749. $secs = ($time % 60);
  7750. if ($time < 0) {
  7751. $hours = 0;
  7752. $mins = 0;
  7753. $secs = 0;
  7754. }
  7755. if ($originFormat == 'js') {
  7756. $formattedTime = trim(sprintf("%02d : %02d : %02d", $hours, $mins, $secs));
  7757. } else {
  7758. $formattedTime = trim(sprintf("%02d$h%02d'%02d\"", $hours, $mins, $secs));
  7759. }
  7760. return $formattedTime;
  7761. }
  7762. /**
  7763. * Create a new empty directory with index.html file.
  7764. *
  7765. * @param string $name The new directory name
  7766. * @param string $parentDirectory Directory parent directory name
  7767. * @deprecated use Resources
  7768. *
  7769. * @return bool Return true if the directory was create. Otherwise return false
  7770. */
  7771. function api_create_protected_dir($name, $parentDirectory)
  7772. {
  7773. $isCreated = false;
  7774. if (!is_writable($parentDirectory)) {
  7775. return false;
  7776. }
  7777. $fullPath = $parentDirectory.api_replace_dangerous_char($name);
  7778. if (mkdir($fullPath, api_get_permissions_for_new_directories(), true)) {
  7779. $fp = fopen($fullPath.'/index.html', 'w');
  7780. if ($fp) {
  7781. if (fwrite($fp, '<html><head></head><body></body></html>')) {
  7782. $isCreated = true;
  7783. }
  7784. }
  7785. fclose($fp);
  7786. }
  7787. return $isCreated;
  7788. }
  7789. /**
  7790. * Sends an email
  7791. * Sender name and email can be specified, if not specified
  7792. * name and email of the platform admin are used.
  7793. *
  7794. * @param string name of recipient
  7795. * @param string email of recipient
  7796. * @param string email subject
  7797. * @param string email body
  7798. * @param string sender name
  7799. * @param string sender e-mail
  7800. * @param array extra headers in form $headers = array($name => $value) to allow parsing
  7801. * @param array data file (path and filename)
  7802. * @param bool True for attaching a embedded file inside content html (optional)
  7803. * @param array Additional parameters
  7804. *
  7805. * @return bool true if mail was sent
  7806. */
  7807. function api_mail_html(
  7808. $recipientName,
  7809. $recipientEmail,
  7810. $subject,
  7811. $body,
  7812. $senderName = '',
  7813. $senderEmail = '',
  7814. $extra_headers = [],
  7815. $data_file = [],
  7816. $embeddedImage = false,
  7817. $additionalParameters = []
  7818. ) {
  7819. if (!api_valid_email($recipientEmail)) {
  7820. return false;
  7821. }
  7822. // Default values
  7823. $notification = new Notification();
  7824. $defaultEmail = $notification->getDefaultPlatformSenderEmail();
  7825. $defaultName = $notification->getDefaultPlatformSenderName();
  7826. // If the parameter is set don't use the admin.
  7827. $senderName = !empty($senderName) ? $senderName : $defaultName;
  7828. $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
  7829. // Reply to first
  7830. $replyToName = '';
  7831. $replyToEmail = '';
  7832. if (isset($extra_headers['reply_to'])) {
  7833. $replyToEmail = $extra_headers['reply_to']['mail'];
  7834. $replyToName = $extra_headers['reply_to']['name'];
  7835. }
  7836. //If the SMTP configuration only accept one sender
  7837. /*if (isset($platform_email['SMTP_UNIQUE_SENDER']) && $platform_email['SMTP_UNIQUE_SENDER']) {
  7838. $senderName = $platform_email['SMTP_FROM_NAME'];
  7839. $senderEmail = $platform_email['SMTP_FROM_EMAIL'];
  7840. $valid = PHPMailer::validateAddress($senderEmail);
  7841. if ($valid) {
  7842. //force-set Sender to $senderEmail, otherwise SetFrom only does it if it is currently empty
  7843. $mail->Sender = $senderEmail;
  7844. }
  7845. }*/
  7846. /*$mail->SetFrom($senderEmail, $senderName);
  7847. $mail->Subject = $subject;
  7848. $mail->AltBody = strip_tags(
  7849. str_replace('<br />', "\n", api_html_entity_decode($message))
  7850. );*/
  7851. /*if (is_array($extra_headers) && count($extra_headers) > 0) {
  7852. foreach ($extra_headers as $key => $value) {
  7853. switch (strtolower($key)) {
  7854. case 'encoding':
  7855. case 'content-transfer-encoding':
  7856. $mail->Encoding = $value;
  7857. break;
  7858. case 'charset':
  7859. $mail->Charset = $value;
  7860. break;
  7861. case 'contenttype':
  7862. case 'content-type':
  7863. $mail->ContentType = $value;
  7864. break;
  7865. default:
  7866. $mail->AddCustomHeader($key.':'.$value);
  7867. break;
  7868. }
  7869. }
  7870. } else {
  7871. if (!empty($extra_headers)) {
  7872. $mail->AddCustomHeader($extra_headers);
  7873. }
  7874. }*/
  7875. // WordWrap the html body (phpMailer only fixes AltBody) FS#2988
  7876. //$mail->Body = $mail->WrapText($mail->Body, $mail->WordWrap);
  7877. try {
  7878. $message = new \Swift_Message($subject);
  7879. $list = api_get_configuration_value('send_all_emails_to');
  7880. if (!empty($list) && isset($list['emails'])) {
  7881. foreach ($list['emails'] as $email) {
  7882. $message->addCc($email);
  7883. }
  7884. }
  7885. // Attachment
  7886. if (!empty($data_file)) {
  7887. foreach ($data_file as $file_attach) {
  7888. if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
  7889. //$message->attach(Swift_Attachment::fromPath($file_attach['path'], $file_attach['filename']);
  7890. $message->attach(
  7891. Swift_Attachment::fromPath($file_attach['path'])->setFilename($file_attach['filename'])
  7892. );
  7893. }
  7894. }
  7895. }
  7896. $noReply = api_get_setting('noreply_email_address');
  7897. $automaticEmailText = '';
  7898. if (!empty($noReply)) {
  7899. $automaticEmailText = '<br />'.get_lang('This is an automatic email message. Please do not reply to it.');
  7900. }
  7901. $params = [
  7902. 'content' => '',
  7903. 'mail_header_style' => api_get_configuration_value('mail_header_style'),
  7904. 'mail_content_style' => api_get_configuration_value('mail_content_style'),
  7905. 'link' => $additionalParameters['link'] ?? '',
  7906. 'automatic_email_text' => $automaticEmailText,
  7907. ];
  7908. $paramsHtml = $paramsText = $params;
  7909. $paramsHtml['content'] = $body;
  7910. $paramsText['content'] = str_replace('<br />', "\n", api_html_entity_decode($body));
  7911. if (!empty($senderEmail)) {
  7912. $message->setFrom([$senderEmail => $senderName]);
  7913. }
  7914. if (!empty($recipientEmail)) {
  7915. $message->setTo([$recipientEmail => $recipientName]);
  7916. }
  7917. if (!empty($replyToEmail)) {
  7918. $message->setReplyTo([$replyToEmail => $replyToName]);
  7919. }
  7920. $message
  7921. ->setBody(
  7922. Container::getTwig()->render(
  7923. 'ChamiloThemeBundle:Mailer:Default/default.html.twig',
  7924. $paramsHtml
  7925. ),
  7926. 'text/html'
  7927. )
  7928. ->addPart(
  7929. Container::getTwig()->render(
  7930. 'ChamiloThemeBundle:Mailer:Default/default.text.twig',
  7931. $paramsText
  7932. ),
  7933. 'text/plain'
  7934. )
  7935. //->setEncoder(\Swift_Encoding::get8BitEncoding())
  7936. ;
  7937. $type = $message->getHeaders()->get('Content-Type');
  7938. $type->setCharset('utf-8');
  7939. Container::getMailer()->send($message);
  7940. return true;
  7941. } catch (Exception $e) {
  7942. error_log($e->getMessage());
  7943. }
  7944. if (!empty($additionalParameters)) {
  7945. $plugin = new AppPlugin();
  7946. $smsPlugin = $plugin->getSMSPluginLibrary();
  7947. if ($smsPlugin) {
  7948. $smsPlugin->send($additionalParameters);
  7949. }
  7950. }
  7951. return 1;
  7952. }
  7953. /**
  7954. * @param string $tool Possible values: GroupManager::GROUP_TOOL_*
  7955. * @param bool $showHeader
  7956. */
  7957. function api_protect_course_group($tool, $showHeader = true)
  7958. {
  7959. $groupId = api_get_group_id();
  7960. if (!empty($groupId)) {
  7961. if (api_is_platform_admin()) {
  7962. return true;
  7963. }
  7964. if (api_is_allowed_to_edit(false, true, true)) {
  7965. return true;
  7966. }
  7967. $userId = api_get_user_id();
  7968. $sessionId = api_get_session_id();
  7969. if (!empty($sessionId)) {
  7970. if (api_is_coach($sessionId, api_get_course_int_id())) {
  7971. return true;
  7972. }
  7973. if (api_is_drh()) {
  7974. if (SessionManager::isUserSubscribedAsHRM($sessionId, $userId)) {
  7975. return true;
  7976. }
  7977. }
  7978. }
  7979. $groupInfo = GroupManager::get_group_properties($groupId);
  7980. // Group doesn't exists
  7981. if (empty($groupInfo)) {
  7982. api_not_allowed($showHeader);
  7983. }
  7984. // Check group access
  7985. $allow = GroupManager::user_has_access(
  7986. $userId,
  7987. $groupInfo['iid'],
  7988. $tool
  7989. );
  7990. if (!$allow) {
  7991. api_not_allowed($showHeader);
  7992. }
  7993. }
  7994. }
  7995. /**
  7996. * Check if a date is in a date range.
  7997. *
  7998. * @param datetime $startDate
  7999. * @param datetime $endDate
  8000. * @param datetime $currentDate
  8001. *
  8002. * @return bool true if date is in rage, false otherwise
  8003. */
  8004. function api_is_date_in_date_range($startDate, $endDate, $currentDate = null)
  8005. {
  8006. $startDate = strtotime(api_get_local_time($startDate));
  8007. $endDate = strtotime(api_get_local_time($endDate));
  8008. $currentDate = strtotime(api_get_local_time($currentDate));
  8009. if ($currentDate >= $startDate && $currentDate <= $endDate) {
  8010. return true;
  8011. }
  8012. return false;
  8013. }
  8014. /**
  8015. * Eliminate the duplicates of a multidimensional array by sending the key.
  8016. *
  8017. * @param array $array multidimensional array
  8018. * @param int $key key to find to compare
  8019. *
  8020. * @return array
  8021. */
  8022. function api_unique_multidim_array($array, $key)
  8023. {
  8024. $temp_array = [];
  8025. $i = 0;
  8026. $key_array = [];
  8027. foreach ($array as $val) {
  8028. if (!in_array($val[$key], $key_array)) {
  8029. $key_array[$i] = $val[$key];
  8030. $temp_array[$i] = $val;
  8031. }
  8032. $i++;
  8033. }
  8034. return $temp_array;
  8035. }
  8036. /**
  8037. * Limit the access to Session Admins when the limit_session_admin_role
  8038. * configuration variable is set to true.
  8039. */
  8040. function api_protect_limit_for_session_admin()
  8041. {
  8042. $limitAdmin = api_get_setting('limit_session_admin_role');
  8043. if (api_is_session_admin() && $limitAdmin === 'true') {
  8044. api_not_allowed(true);
  8045. }
  8046. }
  8047. /**
  8048. * Limits that a session admin has access to list users.
  8049. * When limit_session_admin_list_users configuration variable is set to true.
  8050. */
  8051. function api_protect_session_admin_list_users()
  8052. {
  8053. $limitAdmin = api_get_configuration_value('limit_session_admin_list_users');
  8054. if (api_is_session_admin() && true === $limitAdmin) {
  8055. api_not_allowed(true);
  8056. }
  8057. }
  8058. /**
  8059. * @return bool
  8060. */
  8061. function api_is_student_view_active()
  8062. {
  8063. $studentView = Session::read('studentview');
  8064. return $studentView === 'studentview';
  8065. }
  8066. /**
  8067. * Adds a file inside the upload/$type/id.
  8068. *
  8069. * @param string $type
  8070. * @param array $file
  8071. * @param int $itemId
  8072. * @param string $cropParameters
  8073. * @deprecated use Resources
  8074. *
  8075. * @return array|bool
  8076. */
  8077. function api_upload_file($type, $file, $itemId, $cropParameters = '')
  8078. {
  8079. $upload = process_uploaded_file($file);
  8080. if ($upload) {
  8081. $name = api_replace_dangerous_char($file['name']);
  8082. // No "dangerous" files
  8083. $name = disable_dangerous_file($name);
  8084. $pathId = '/'.substr((string) $itemId, 0, 1).'/'.$itemId.'/';
  8085. $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
  8086. if (!is_dir($path)) {
  8087. mkdir($path, api_get_permissions_for_new_directories(), true);
  8088. }
  8089. $pathToSave = $path.$name;
  8090. $result = moveUploadedFile($file, $pathToSave);
  8091. if ($result) {
  8092. if (!empty($cropParameters)) {
  8093. $image = new Image($pathToSave);
  8094. $image->crop($cropParameters);
  8095. }
  8096. return ['path_to_save' => $pathId.$name];
  8097. }
  8098. return false;
  8099. }
  8100. }
  8101. /**
  8102. * @param string $type
  8103. * @param int $itemId
  8104. * @param string $file
  8105. *
  8106. * @return bool
  8107. */
  8108. function api_get_uploaded_web_url($type, $itemId, $file)
  8109. {
  8110. return api_get_uploaded_file($type, $itemId, $file, true);
  8111. }
  8112. /**
  8113. * @param string $type
  8114. * @param int $itemId
  8115. * @param string $file
  8116. * @param bool $getUrl
  8117. *
  8118. * @return bool
  8119. */
  8120. function api_get_uploaded_file($type, $itemId, $file, $getUrl = false)
  8121. {
  8122. $itemId = (int) $itemId;
  8123. $pathId = '/'.substr((string) $itemId, 0, 1).'/'.$itemId.'/';
  8124. $path = api_get_path(SYS_UPLOAD_PATH).$type.$pathId;
  8125. $file = basename($file);
  8126. $file = $path.'/'.$file;
  8127. if (Security::check_abs_path($file, $path) && is_file($file) && file_exists($file)) {
  8128. if ($getUrl) {
  8129. return str_replace(api_get_path(SYS_UPLOAD_PATH), api_get_path(WEB_UPLOAD_PATH), $file);
  8130. }
  8131. return $file;
  8132. }
  8133. return false;
  8134. }
  8135. /**
  8136. * @param string $type
  8137. * @param int $itemId
  8138. * @param string $file
  8139. * @param string $title
  8140. */
  8141. function api_download_uploaded_file($type, $itemId, $file, $title = '')
  8142. {
  8143. $file = api_get_uploaded_file($type, $itemId, $file);
  8144. if ($file) {
  8145. if (Security::check_abs_path($file, api_get_path(SYS_UPLOAD_PATH).$type)) {
  8146. DocumentManager::file_send_for_download($file, true, $title);
  8147. exit;
  8148. }
  8149. }
  8150. api_not_allowed(true);
  8151. }
  8152. /**
  8153. * @param string $type
  8154. * @param string $file
  8155. */
  8156. function api_remove_uploaded_file($type, $file)
  8157. {
  8158. $typePath = api_get_path(SYS_UPLOAD_PATH).$type;
  8159. $path = $typePath.'/'.$file;
  8160. if (Security::check_abs_path($path, $typePath) && file_exists($path) && is_file($path)) {
  8161. unlink($path);
  8162. }
  8163. }
  8164. /**
  8165. * @param string $type
  8166. * @param int $itemId
  8167. * @param string $file
  8168. *
  8169. * @return bool
  8170. */
  8171. function api_remove_uploaded_file_by_id($type, $itemId, $file)
  8172. {
  8173. $file = api_get_uploaded_file($type, $itemId, $file, false);
  8174. $typePath = api_get_path(SYS_UPLOAD_PATH).$type;
  8175. if (Security::check_abs_path($file, $typePath) && file_exists($file) && is_file($file)) {
  8176. unlink($file);
  8177. return true;
  8178. }
  8179. return false;
  8180. }
  8181. /**
  8182. * Converts string value to float value.
  8183. *
  8184. * 3.141516 => 3.141516
  8185. * 3,141516 => 3.141516
  8186. *
  8187. * @todo WIP
  8188. *
  8189. * @param string $number
  8190. *
  8191. * @return float
  8192. */
  8193. function api_float_val($number)
  8194. {
  8195. $number = (float) str_replace(',', '.', trim($number));
  8196. return $number;
  8197. }
  8198. /**
  8199. * Converts float values
  8200. * Example if $decimals = 2.
  8201. *
  8202. * 3.141516 => 3.14
  8203. * 3,141516 => 3,14
  8204. *
  8205. * @param string $number number in iso code
  8206. * @param int $decimals
  8207. * @param string $decimalSeparator
  8208. * @param string $thousandSeparator
  8209. *
  8210. * @return bool|string
  8211. */
  8212. function api_number_format($number, $decimals = 0, $decimalSeparator = '.', $thousandSeparator = ',')
  8213. {
  8214. $number = api_float_val($number);
  8215. return number_format($number, $decimals, $decimalSeparator, $thousandSeparator);
  8216. }
  8217. /**
  8218. * Set location url with a exit break by default.
  8219. *
  8220. * @param $url
  8221. * @param bool $exit
  8222. */
  8223. function location($url, $exit = true)
  8224. {
  8225. header('Location: '.$url);
  8226. if ($exit) {
  8227. exit;
  8228. }
  8229. }
  8230. /**
  8231. * @return string
  8232. */
  8233. function api_get_web_url()
  8234. {
  8235. if (api_get_setting('server_type') === 'test') {
  8236. return api_get_path(WEB_PATH).'web/app_dev.php/';
  8237. } else {
  8238. return api_get_path(WEB_PATH).'web/';
  8239. }
  8240. }
  8241. /**
  8242. * @param string $from
  8243. * @param string $to
  8244. *
  8245. * @return string
  8246. */
  8247. function api_get_relative_path($from, $to)
  8248. {
  8249. // some compatibility fixes for Windows paths
  8250. $from = is_dir($from) ? rtrim($from, '\/').'/' : $from;
  8251. $to = is_dir($to) ? rtrim($to, '\/').'/' : $to;
  8252. $from = str_replace('\\', '/', $from);
  8253. $to = str_replace('\\', '/', $to);
  8254. $from = explode('/', $from);
  8255. $to = explode('/', $to);
  8256. $relPath = $to;
  8257. foreach ($from as $depth => $dir) {
  8258. // find first non-matching dir
  8259. if ($dir === $to[$depth]) {
  8260. // ignore this directory
  8261. array_shift($relPath);
  8262. } else {
  8263. // get number of remaining dirs to $from
  8264. $remaining = count($from) - $depth;
  8265. if ($remaining > 1) {
  8266. // add traversals up to first matching dir
  8267. $padLength = (count($relPath) + $remaining - 1) * -1;
  8268. $relPath = array_pad($relPath, $padLength, '..');
  8269. break;
  8270. } else {
  8271. $relPath[0] = './'.$relPath[0];
  8272. }
  8273. }
  8274. }
  8275. return implode('/', $relPath);
  8276. }
  8277. /**
  8278. * Unserialize content using Brummann\Polyfill\Unserialize.
  8279. *
  8280. * @param string $type
  8281. * @param string $serialized
  8282. * @param bool $ignoreErrors. Optional.
  8283. *
  8284. * @return mixed
  8285. */
  8286. function api_unserialize_content($type, $serialized, $ignoreErrors = false)
  8287. {
  8288. switch ($type) {
  8289. case 'career':
  8290. case 'sequence_graph':
  8291. $allowedClasses = [Graph::class, VerticesMap::class, Vertices::class, Edges::class];
  8292. break;
  8293. case 'lp':
  8294. $allowedClasses = [
  8295. learnpath::class,
  8296. learnpathItem::class,
  8297. aicc::class,
  8298. aiccBlock::class,
  8299. aiccItem::class,
  8300. aiccObjective::class,
  8301. aiccResource::class,
  8302. scorm::class,
  8303. scormItem::class,
  8304. scormMetadata::class,
  8305. scormOrganization::class,
  8306. scormResource::class,
  8307. Link::class,
  8308. LpItem::class,
  8309. ];
  8310. break;
  8311. case 'course':
  8312. $allowedClasses = [
  8313. Course::class,
  8314. Announcement::class,
  8315. Attendance::class,
  8316. CalendarEvent::class,
  8317. CourseCopyLearnpath::class,
  8318. CourseCopyTestCategory::class,
  8319. CourseDescription::class,
  8320. CourseSession::class,
  8321. Document::class,
  8322. Forum::class,
  8323. ForumCategory::class,
  8324. ForumPost::class,
  8325. ForumTopic::class,
  8326. Glossary::class,
  8327. GradeBookBackup::class,
  8328. Link::class,
  8329. LinkCategory::class,
  8330. Quiz::class,
  8331. QuizQuestion::class,
  8332. QuizQuestionOption::class,
  8333. ScormDocument::class,
  8334. Survey::class,
  8335. SurveyInvitation::class,
  8336. SurveyQuestion::class,
  8337. Thematic::class,
  8338. ToolIntro::class,
  8339. Wiki::class,
  8340. Work::class,
  8341. stdClass::class,
  8342. ];
  8343. break;
  8344. case 'not_allowed_classes':
  8345. default:
  8346. $allowedClasses = false;
  8347. }
  8348. if ($ignoreErrors) {
  8349. return @Unserialize::unserialize(
  8350. $serialized,
  8351. ['allowed_classes' => $allowedClasses]
  8352. );
  8353. }
  8354. return Unserialize::unserialize(
  8355. $serialized,
  8356. ['allowed_classes' => $allowedClasses]
  8357. );
  8358. }
  8359. /**
  8360. * @param string $template
  8361. *
  8362. * @return string
  8363. */
  8364. function api_find_template($template)
  8365. {
  8366. return Template::findTemplateFilePath($template);
  8367. }
  8368. /**
  8369. * @return array
  8370. */
  8371. function api_get_language_list_for_flag()
  8372. {
  8373. $table = Database::get_main_table(TABLE_MAIN_LANGUAGE);
  8374. $sql = "SELECT english_name, isocode FROM $table
  8375. ORDER BY original_name ASC";
  8376. static $languages = [];
  8377. if (empty($languages)) {
  8378. $result = Database::query($sql);
  8379. while ($row = Database::fetch_array($result)) {
  8380. $languages[$row['english_name']] = $row['isocode'];
  8381. }
  8382. $languages['english'] = 'gb';
  8383. }
  8384. return $languages;
  8385. }
  8386. /**
  8387. * @param string $name
  8388. *
  8389. * @return \ZipStream\ZipStream
  8390. */
  8391. function api_create_zip($name)
  8392. {
  8393. $zipStreamOptions = new \ZipStream\Option\Archive();
  8394. $zipStreamOptions->setSendHttpHeaders(true);
  8395. $zipStreamOptions->setContentDisposition('attachment');
  8396. $zipStreamOptions->setContentType('application/x-zip');
  8397. $zip = new \ZipStream\ZipStream($name, $zipStreamOptions);
  8398. return $zip;
  8399. }
  8400. /**
  8401. * @return string
  8402. */
  8403. function api_get_language_translate_html()
  8404. {
  8405. $translate = api_get_configuration_value('translate_html');
  8406. if (!$translate) {
  8407. return '';
  8408. }
  8409. $languageList = api_get_languages();
  8410. $hideAll = '';
  8411. foreach ($languageList['all'] as $language) {
  8412. $hideAll .= '
  8413. $("span:lang('.$language['isocode'].')").filter(
  8414. function(e, val) {
  8415. // Only find the spans if they have set the lang
  8416. if ($(this).attr("lang") == null) {
  8417. return false;
  8418. }
  8419. // Ignore ckeditor classes
  8420. return !this.className.match(/cke(.*)/);
  8421. }).hide();'."\n";
  8422. }
  8423. $userInfo = api_get_user_info();
  8424. $languageId = api_get_language_id($userInfo['language']);
  8425. $languageInfo = api_get_language_info($languageId);
  8426. $isoCode = 'en';
  8427. if (!empty($languageInfo)) {
  8428. $isoCode = $languageInfo['isocode'];
  8429. }
  8430. return '
  8431. $(function() {
  8432. '.$hideAll.'
  8433. var defaultLanguageFromUser = "'.$isoCode.'";
  8434. $("span:lang('.$isoCode.')").filter(
  8435. function() {
  8436. // Ignore ckeditor classes
  8437. return !this.className.match(/cke(.*)/);
  8438. }).show();
  8439. var defaultLanguage = "";
  8440. var langFromUserFound = false;
  8441. $(this).find("span").filter(
  8442. function() {
  8443. // Ignore ckeditor classes
  8444. return !this.className.match(/cke(.*)/);
  8445. }).each(function() {
  8446. defaultLanguage = $(this).attr("lang");
  8447. if (defaultLanguage) {
  8448. $(this).before().next("br").remove();
  8449. if (defaultLanguageFromUser == defaultLanguage) {
  8450. langFromUserFound = true;
  8451. }
  8452. }
  8453. });
  8454. // Show default language
  8455. if (langFromUserFound == false && defaultLanguage) {
  8456. $("span:lang("+defaultLanguage+")").filter(
  8457. function() {
  8458. // Ignore ckeditor classes
  8459. return !this.className.match(/cke(.*)/);
  8460. }).show();
  8461. }
  8462. });
  8463. ';
  8464. }