document.lib.php 261 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class DocumentManager
  5. * This is the document library for Chamilo.
  6. * It is / will be used to provide a service layer to all document-using tools.
  7. * and eliminate code duplication fro group documents, scorm documents, main documents.
  8. * Include/require it in your code to use its functionality.
  9. *
  10. * @package chamilo.library
  11. */
  12. class DocumentManager
  13. {
  14. /**
  15. * Construct
  16. */
  17. private function __construct()
  18. {
  19. }
  20. /**
  21. * @param string $course_code
  22. *
  23. * @return int the document folder quota for the current course in bytes
  24. * or the default quota
  25. */
  26. public static function get_course_quota($course_code = null)
  27. {
  28. if (empty($course_code)) {
  29. $course_info = api_get_course_info();
  30. } else {
  31. $course_info = api_get_course_info($course_code);
  32. }
  33. $course_quota = null;
  34. if (empty($course_info)) {
  35. return DEFAULT_DOCUMENT_QUOTA;
  36. } else {
  37. $course_quota = $course_info['disk_quota'];
  38. }
  39. if (is_null($course_quota) || empty($course_quota)) {
  40. // Course table entry for quota was null, then use default value
  41. $course_quota = DEFAULT_DOCUMENT_QUOTA;
  42. }
  43. return $course_quota;
  44. }
  45. /**
  46. * Get the content type of a file by checking the extension
  47. * We could use mime_content_type() with php-versions > 4.3,
  48. * but this doesn't work as it should on Windows installations
  49. *
  50. * @param string $filename or boolean TRUE to return complete array
  51. * @author ? first version
  52. * @author Bert Vanderkimpen
  53. * @return string
  54. *
  55. */
  56. public static function file_get_mime_type($filename)
  57. {
  58. // All MIME types in an array (from 1.6, this is the authorative source)
  59. // Please, keep this alphabetical if you add something to this list!
  60. $mime_types = array(
  61. 'ai' => 'application/postscript',
  62. 'aif' => 'audio/x-aiff',
  63. 'aifc' => 'audio/x-aiff',
  64. 'aiff' => 'audio/x-aiff',
  65. 'asf' => 'video/x-ms-asf',
  66. 'asc' => 'text/plain',
  67. 'au' => 'audio/basic',
  68. 'avi' => 'video/x-msvideo',
  69. 'bcpio' => 'application/x-bcpio',
  70. 'bin' => 'application/octet-stream',
  71. 'bmp' => 'image/bmp',
  72. 'cdf' => 'application/x-netcdf',
  73. 'class' => 'application/octet-stream',
  74. 'cpio' => 'application/x-cpio',
  75. 'cpt' => 'application/mac-compactpro',
  76. 'csh' => 'application/x-csh',
  77. 'css' => 'text/css',
  78. 'dcr' => 'application/x-director',
  79. 'dir' => 'application/x-director',
  80. 'djv' => 'image/vnd.djvu',
  81. 'djvu' => 'image/vnd.djvu',
  82. 'dll' => 'application/octet-stream',
  83. 'dmg' => 'application/x-diskcopy',
  84. 'dms' => 'application/octet-stream',
  85. 'doc' => 'application/msword',
  86. 'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
  87. 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  88. 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
  89. 'dvi' => 'application/x-dvi',
  90. 'dwg' => 'application/vnd.dwg',
  91. 'dwf' => 'application/vnd.dwf',
  92. 'dxf' => 'application/vnd.dxf',
  93. 'dxr' => 'application/x-director',
  94. 'eps' => 'application/postscript',
  95. 'epub' => 'application/epub+zip',
  96. 'etx' => 'text/x-setext',
  97. 'exe' => 'application/octet-stream',
  98. 'ez' => 'application/andrew-inset',
  99. 'gif' => 'image/gif',
  100. 'gtar' => 'application/x-gtar',
  101. 'gz' => 'application/x-gzip',
  102. 'hdf' => 'application/x-hdf',
  103. 'hqx' => 'application/mac-binhex40',
  104. 'htm' => 'text/html',
  105. 'html' => 'text/html',
  106. 'ice' => 'x-conference-xcooltalk',
  107. 'ief' => 'image/ief',
  108. 'iges' => 'model/iges',
  109. 'igs' => 'model/iges',
  110. 'jar' => 'application/java-archiver',
  111. 'jpe' => 'image/jpeg',
  112. 'jpeg' => 'image/jpeg',
  113. 'jpg' => 'image/jpeg',
  114. 'js' => 'application/x-javascript',
  115. 'kar' => 'audio/midi',
  116. 'lam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
  117. 'latex' => 'application/x-latex',
  118. 'lha' => 'application/octet-stream',
  119. 'log' => 'text/plain',
  120. 'lzh' => 'application/octet-stream',
  121. 'm1a' => 'audio/mpeg',
  122. 'm2a' => 'audio/mpeg',
  123. 'm3u' => 'audio/x-mpegurl',
  124. 'man' => 'application/x-troff-man',
  125. 'me' => 'application/x-troff-me',
  126. 'mesh' => 'model/mesh',
  127. 'mid' => 'audio/midi',
  128. 'midi' => 'audio/midi',
  129. 'mov' => 'video/quicktime',
  130. 'movie' => 'video/x-sgi-movie',
  131. 'mp2' => 'audio/mpeg',
  132. 'mp3' => 'audio/mpeg',
  133. 'mp4' => 'video/mpeg4-generic',
  134. 'mpa' => 'audio/mpeg',
  135. 'mpe' => 'video/mpeg',
  136. 'mpeg' => 'video/mpeg',
  137. 'mpg' => 'video/mpeg',
  138. 'mpga' => 'audio/mpeg',
  139. 'ms' => 'application/x-troff-ms',
  140. 'msh' => 'model/mesh',
  141. 'mxu' => 'video/vnd.mpegurl',
  142. 'nc' => 'application/x-netcdf',
  143. 'oda' => 'application/oda',
  144. 'oga' => 'audio/ogg',
  145. 'ogg' => 'application/ogg',
  146. 'ogx' => 'application/ogg',
  147. 'ogv' => 'video/ogg',
  148. 'pbm' => 'image/x-portable-bitmap',
  149. 'pct' => 'image/pict',
  150. 'pdb' => 'chemical/x-pdb',
  151. 'pdf' => 'application/pdf',
  152. 'pgm' => 'image/x-portable-graymap',
  153. 'pgn' => 'application/x-chess-pgn',
  154. 'pict' => 'image/pict',
  155. 'png' => 'image/png',
  156. 'pnm' => 'image/x-portable-anymap',
  157. 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
  158. 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
  159. 'pps' => 'application/vnd.ms-powerpoint',
  160. 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
  161. 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
  162. 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
  163. 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
  164. 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  165. 'ppm' => 'image/x-portable-pixmap',
  166. 'ppt' => 'application/vnd.ms-powerpoint',
  167. 'pps' => 'application/vnd.ms-powerpoint',
  168. 'ps' => 'application/postscript',
  169. 'qt' => 'video/quicktime',
  170. 'ra' => 'audio/x-realaudio',
  171. 'ram' => 'audio/x-pn-realaudio',
  172. 'rar' => 'image/x-rar-compressed',
  173. 'ras' => 'image/x-cmu-raster',
  174. 'rgb' => 'image/x-rgb',
  175. 'rm' => 'audio/x-pn-realaudio',
  176. 'roff' => 'application/x-troff',
  177. 'rpm' => 'audio/x-pn-realaudio-plugin',
  178. 'rtf' => 'text/rtf',
  179. 'rtx' => 'text/richtext',
  180. 'sgm' => 'text/sgml',
  181. 'sgml' => 'text/sgml',
  182. 'sh' => 'application/x-sh',
  183. 'shar' => 'application/x-shar',
  184. 'silo' => 'model/mesh',
  185. 'sib' => 'application/X-Sibelius-Score',
  186. 'sit' => 'application/x-stuffit',
  187. 'skd' => 'application/x-koan',
  188. 'skm' => 'application/x-koan',
  189. 'skp' => 'application/x-koan',
  190. 'skt' => 'application/x-koan',
  191. 'smi' => 'application/smil',
  192. 'smil' => 'application/smil',
  193. 'snd' => 'audio/basic',
  194. 'so' => 'application/octet-stream',
  195. 'spl' => 'application/x-futuresplash',
  196. 'src' => 'application/x-wais-source',
  197. 'sv4cpio' => 'application/x-sv4cpio',
  198. 'sv4crc' => 'application/x-sv4crc',
  199. 'svf' => 'application/vnd.svf',
  200. 'svg' => 'image/svg+xml',
  201. //'svgz' => 'image/svg+xml',
  202. 'swf' => 'application/x-shockwave-flash',
  203. 'sxc' => 'application/vnd.sun.xml.calc',
  204. 'sxi' => 'application/vnd.sun.xml.impress',
  205. 'sxw' => 'application/vnd.sun.xml.writer',
  206. 't' => 'application/x-troff',
  207. 'tar' => 'application/x-tar',
  208. 'tcl' => 'application/x-tcl',
  209. 'tex' => 'application/x-tex',
  210. 'texi' => 'application/x-texinfo',
  211. 'texinfo' => 'application/x-texinfo',
  212. 'tga' => 'image/x-targa',
  213. 'tif' => 'image/tif',
  214. 'tiff' => 'image/tiff',
  215. 'tr' => 'application/x-troff',
  216. 'tsv' => 'text/tab-seperated-values',
  217. 'txt' => 'text/plain',
  218. 'ustar' => 'application/x-ustar',
  219. 'vcd' => 'application/x-cdlink',
  220. 'vrml' => 'model/vrml',
  221. 'wav' => 'audio/x-wav',
  222. 'wbmp' => 'image/vnd.wap.wbmp',
  223. 'wbxml' => 'application/vnd.wap.wbxml',
  224. 'wml' => 'text/vnd.wap.wml',
  225. 'wmlc' => 'application/vnd.wap.wmlc',
  226. 'wmls' => 'text/vnd.wap.wmlscript',
  227. 'wmlsc' => 'application/vnd.wap.wmlscriptc',
  228. 'wma' => 'audio/x-ms-wma',
  229. 'wmv' => 'video/x-ms-wmv',
  230. 'wrl' => 'model/vrml',
  231. 'xbm' => 'image/x-xbitmap',
  232. 'xht' => 'application/xhtml+xml',
  233. 'xhtml' => 'application/xhtml+xml',
  234. 'xls' => 'application/vnd.ms-excel',
  235. 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
  236. 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
  237. 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  238. 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
  239. 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
  240. 'xml' => 'text/xml',
  241. 'xpm' => 'image/x-xpixmap',
  242. 'xsl' => 'text/xml',
  243. 'xwd' => 'image/x-windowdump',
  244. 'xyz' => 'chemical/x-xyz',
  245. 'zip' => 'application/zip'
  246. );
  247. if ($filename === true) {
  248. return $mime_types;
  249. }
  250. //get the extension of the file
  251. $extension = explode('.', $filename);
  252. //$filename will be an array if a . was found
  253. if (is_array($extension)) {
  254. $extension = strtolower($extension[sizeof($extension) - 1]);
  255. } else {
  256. //file without extension
  257. $extension = 'empty';
  258. }
  259. //if the extension is found, return the content type
  260. if (isset($mime_types[$extension])) {
  261. return $mime_types[$extension];
  262. }
  263. //else return octet-stream
  264. return 'application/octet-stream';
  265. }
  266. /**
  267. * @param string
  268. * @param string
  269. * @return true if the user is allowed to see the document, false otherwise
  270. * @author Sergio A Kessler, first version
  271. * @author Roan Embrechts, bugfix
  272. * @todo not only check if a file is visible, but also check if the user is allowed to see the file??
  273. */
  274. public static function file_visible_to_user($this_course, $doc_url)
  275. {
  276. $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
  277. if ($is_allowed_to_edit) {
  278. return true;
  279. } else {
  280. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  281. $tbl_item_property = $this_course.'item_property';
  282. $doc_url = Database::escape_string($doc_url);
  283. $query = "SELECT 1 FROM $tbl_document AS docs,$tbl_item_property AS props
  284. WHERE
  285. props.tool = 'document' AND
  286. docs.id=props.ref AND
  287. props.visibility <> '1' AND
  288. docs.path = '$doc_url'";
  289. $result = Database::query($query);
  290. return Database::num_rows($result) == 0;
  291. }
  292. }
  293. /**
  294. * This function streams a file to the client
  295. *
  296. * @param string $full_file_name
  297. * @param boolean $forced
  298. * @param string $name
  299. * @param string $fixLinksHttpToHttps change file content from http to https
  300. *
  301. * @return false if file doesn't exist, true if stream succeeded
  302. */
  303. public static function file_send_for_download(
  304. $full_file_name,
  305. $forced = false,
  306. $name = '',
  307. $fixLinksHttpToHttps = false
  308. ) {
  309. session_write_close(); //we do not need write access to session anymore
  310. if (!is_file($full_file_name)) {
  311. return false;
  312. }
  313. $filename = ($name == '') ? basename($full_file_name) : api_replace_dangerous_char($name);
  314. $len = filesize($full_file_name);
  315. // Fixing error when file name contains a ","
  316. $filename = str_replace(',', '', $filename);
  317. $sendFileHeaders = api_get_configuration_value('enable_x_sendfile_headers');
  318. if ($forced) {
  319. // Force the browser to save the file instead of opening it
  320. if (isset($sendFileHeaders) &&
  321. !empty($sendFileHeaders)) {
  322. header("X-Sendfile: $filename");
  323. }
  324. header('Content-type: application/octet-stream');
  325. header('Content-length: '.$len);
  326. if (preg_match("/MSIE 5.5/", $_SERVER['HTTP_USER_AGENT'])) {
  327. header('Content-Disposition: filename= '.$filename);
  328. } else {
  329. header('Content-Disposition: attachment; filename= '.$filename);
  330. }
  331. if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
  332. header('Pragma: ');
  333. header('Cache-Control: ');
  334. header('Cache-Control: public'); // IE cannot download from sessions without a cache
  335. }
  336. header('Content-Description: '.$filename);
  337. header('Content-Transfer-Encoding: binary');
  338. $res = fopen($full_file_name, 'r');
  339. fpassthru($res);
  340. return true;
  341. } else {
  342. //no forced download, just let the browser decide what to do according to the mimetype
  343. $content_type = self::file_get_mime_type($filename);
  344. $lpFixedEncoding = api_get_configuration_value('lp_fixed_encoding');
  345. // Commented to let courses content to be cached in order to improve performance:
  346. //header('Expires: Wed, 01 Jan 1990 00:00:00 GMT');
  347. //header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
  348. // Commented to avoid double caching declaration when playing with IE and HTTPS
  349. //header('Cache-Control: no-cache, must-revalidate');
  350. //header('Pragma: no-cache');
  351. switch ($content_type) {
  352. case 'text/html':
  353. if (isset($lpFixedEncoding) && $lpFixedEncoding === 'true') {
  354. $content_type .= '; charset=UTF-8';
  355. } else {
  356. $encoding = @api_detect_encoding_html(file_get_contents($full_file_name));
  357. if (!empty($encoding)) {
  358. $content_type .= '; charset='.$encoding;
  359. }
  360. }
  361. break;
  362. case 'text/plain':
  363. if (isset($lpFixedEncoding) && $lpFixedEncoding === 'true') {
  364. $content_type .= '; charset=UTF-8';
  365. } else {
  366. $encoding = @api_detect_encoding(strip_tags(file_get_contents($full_file_name)));
  367. if (!empty($encoding)) {
  368. $content_type .= '; charset='.$encoding;
  369. }
  370. }
  371. break;
  372. case 'application/vnd.dwg':
  373. case 'application/vnd.dwf':
  374. header('Content-type: application/octet-stream');
  375. break;
  376. }
  377. header('Content-type: '.$content_type);
  378. header('Content-Length: '.$len);
  379. $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
  380. if (strpos($user_agent, 'msie')) {
  381. header('Content-Disposition: ; filename= '.$filename);
  382. } else {
  383. header('Content-Disposition: inline; filename= '.$filename);
  384. }
  385. if ($fixLinksHttpToHttps) {
  386. $content = file_get_contents($full_file_name);
  387. $content = str_replace(
  388. array('http%3A%2F%2F', 'http://'),
  389. array('https%3A%2F%2F', 'https://'),
  390. $content
  391. );
  392. echo $content;
  393. } else {
  394. readfile($full_file_name);
  395. }
  396. return true;
  397. }
  398. }
  399. /**
  400. * This function streams a string to the client for download.
  401. * You have to ensure that the calling script then stops processing (exit();)
  402. * otherwise it may cause subsequent use of the page to want to download
  403. * other pages in php rather than interpreting them.
  404. *
  405. * @param string $full_string The string contents
  406. * @param boolean $forced Whether "save" mode is forced (or opening directly authorized)
  407. * @param string $name The name of the file in the end (including extension)
  408. *
  409. * @return false if file doesn't exist, true if stream succeeded
  410. */
  411. public static function string_send_for_download($full_string, $forced = false, $name = '')
  412. {
  413. $filename = $name;
  414. $len = strlen($full_string);
  415. if ($forced) {
  416. //force the browser to save the file instead of opening it
  417. header('Content-type: application/octet-stream');
  418. //header('Content-Type: application/force-download');
  419. header('Content-length: '.$len);
  420. if (preg_match("/MSIE 5.5/", $_SERVER['HTTP_USER_AGENT'])) {
  421. header('Content-Disposition: filename= '.$filename);
  422. } else {
  423. header('Content-Disposition: attachment; filename= '.$filename);
  424. }
  425. if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
  426. header('Pragma: ');
  427. header('Cache-Control: ');
  428. header('Cache-Control: public'); // IE cannot download from sessions without a cache
  429. }
  430. header('Content-Description: '.$filename);
  431. header('Content-transfer-encoding: binary');
  432. echo $full_string;
  433. return true;
  434. //You have to ensure that the calling script then stops processing (exit();)
  435. //otherwise it may cause subsequent use of the page to want to download
  436. //other pages in php rather than interpreting them.
  437. } else {
  438. //no forced download, just let the browser decide what to do according to the mimetype
  439. $content_type = self::file_get_mime_type($filename);
  440. header('Expires: Wed, 01 Jan 1990 00:00:00 GMT');
  441. header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
  442. header('Cache-Control: no-cache, must-revalidate');
  443. header('Pragma: no-cache');
  444. switch ($content_type) {
  445. case 'text/html':
  446. $encoding = @api_detect_encoding_html($full_string);
  447. if (!empty($encoding)) {
  448. $content_type .= '; charset='.$encoding;
  449. }
  450. break;
  451. case 'text/plain':
  452. $encoding = @api_detect_encoding(strip_tags($full_string));
  453. if (!empty($encoding)) {
  454. $content_type .= '; charset='.$encoding;
  455. }
  456. break;
  457. }
  458. header('Content-type: '.$content_type);
  459. header('Content-Length: '.$len);
  460. $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
  461. if (strpos($user_agent, 'msie')) {
  462. header('Content-Disposition: ; filename= '.$filename);
  463. } else {
  464. header('Content-Disposition: inline; filename= '.$filename);
  465. }
  466. echo($full_string);
  467. //You have to ensure that the calling script then stops processing (exit();)
  468. //otherwise it may cause subsequent use of the page to want to download
  469. //other pages in php rather than interpreting them.
  470. return true;
  471. }
  472. }
  473. /**
  474. * Session folder filters
  475. *
  476. * @param string $path
  477. * @param int $sessionId
  478. *
  479. * @return null|string
  480. */
  481. public static function getSessionFolderFilters($path, $sessionId)
  482. {
  483. $sessionId = intval($sessionId);
  484. $condition = null;
  485. if (!empty($sessionId)) {
  486. // Chat folder filter
  487. if ($path == '/chat_files') {
  488. $condition .= " AND (docs.session_id = '$sessionId') ";
  489. }
  490. // share_folder filter
  491. $condition .= " AND docs.path != '/shared_folder' ";
  492. }
  493. return $condition;
  494. }
  495. /**
  496. * Fetches all document data for the given user/group
  497. *
  498. * @param array $_course
  499. * @param string $path
  500. * @param int $to_group_id iid
  501. * @param int $to_user_id
  502. * @param boolean $can_see_invisible
  503. * @param boolean $search
  504. * @param int $sessionId
  505. * @return array with all document data
  506. */
  507. public static function get_all_document_data(
  508. $_course,
  509. $path = '/',
  510. $to_group_id = 0,
  511. $to_user_id = null,
  512. $can_see_invisible = false,
  513. $search = false,
  514. $sessionId = 0
  515. ) {
  516. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  517. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  518. $userGroupFilter = '';
  519. if (!is_null($to_user_id)) {
  520. $to_user_id = intval($to_user_id);
  521. $userGroupFilter = "last.to_user_id = $to_user_id";
  522. if (empty($to_user_id)) {
  523. $userGroupFilter = " (last.to_user_id = 0 OR last.to_user_id IS NULL) ";
  524. }
  525. } else {
  526. $to_group_id = intval($to_group_id);
  527. $userGroupFilter = "last.to_group_id = $to_group_id";
  528. if (empty($to_group_id)) {
  529. $userGroupFilter = "( last.to_group_id = 0 OR last.to_group_id IS NULL) ";
  530. }
  531. }
  532. // Escape underscores in the path so they don't act as a wildcard
  533. $originalPath = $path;
  534. $path = str_replace('_', '\_', $path);
  535. $visibility_bit = ' <> 2';
  536. // The given path will not end with a slash, unless it's the root '/'
  537. // so no root -> add slash
  538. $added_slash = $path == '/' ? '' : '/';
  539. // Condition for the session
  540. $sessionId = $sessionId ?: api_get_session_id();
  541. $condition_session = " AND (last.session_id = '$sessionId' OR (last.session_id = '0' OR last.session_id IS NULL) )";
  542. $condition_session .= self::getSessionFolderFilters($originalPath, $sessionId);
  543. $sharedCondition = null;
  544. if ($originalPath == '/shared_folder') {
  545. $students = CourseManager::get_user_list_from_course_code($_course['code'], $sessionId);
  546. if (!empty($students)) {
  547. $conditionList = array();
  548. foreach ($students as $studentId => $studentInfo) {
  549. $conditionList[] = '/shared_folder/sf_user_'.$studentInfo['user_id'];
  550. }
  551. $sharedCondition .= ' AND docs.path IN ("'.implode('","', $conditionList).'")';
  552. }
  553. }
  554. $sql = "SELECT
  555. docs.id,
  556. docs.filetype,
  557. docs.path,
  558. docs.title,
  559. docs.comment,
  560. docs.size,
  561. docs.readonly,
  562. docs.session_id,
  563. last.session_id item_property_session_id,
  564. last.lastedit_date,
  565. last.visibility,
  566. last.insert_user_id
  567. FROM $TABLE_ITEMPROPERTY AS last
  568. INNER JOIN $TABLE_DOCUMENT AS docs
  569. ON (
  570. docs.id = last.ref AND
  571. docs.c_id = last.c_id
  572. )
  573. WHERE
  574. last.tool = '".TOOL_DOCUMENT."' AND
  575. docs.c_id = {$_course['real_id']} AND
  576. last.c_id = {$_course['real_id']} AND
  577. docs.path LIKE '".Database::escape_string($path.$added_slash.'%')."' AND
  578. docs.path NOT LIKE '" . Database::escape_string($path.$added_slash.'%/%')."' AND
  579. docs.path NOT LIKE '%_DELETED_%' AND
  580. $userGroupFilter AND
  581. last.visibility $visibility_bit
  582. $condition_session
  583. $sharedCondition
  584. ";
  585. $result = Database::query($sql);
  586. $doc_list = array();
  587. $document_data = array();
  588. $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
  589. $isCoach = api_is_coach();
  590. if ($result !== false && Database::num_rows($result) != 0) {
  591. while ($row = Database::fetch_array($result, 'ASSOC')) {
  592. if ($isCoach) {
  593. // Looking for course items that are invisible to hide it in the session
  594. if (in_array($row['id'], array_keys($doc_list))) {
  595. if ($doc_list[$row['id']]['item_property_session_id'] == 0 &&
  596. $doc_list[$row['id']]['session_id'] == 0
  597. ) {
  598. if ($doc_list[$row['id']]['visibility'] == 0) {
  599. unset($document_data[$row['id']]);
  600. continue;
  601. }
  602. }
  603. }
  604. $doc_list[$row['id']] = $row;
  605. }
  606. if (!$isCoach && !$is_allowed_to_edit) {
  607. $doc_list[] = $row;
  608. }
  609. if ($row['filetype'] == 'file' &&
  610. pathinfo($row['path'], PATHINFO_EXTENSION) == 'html'
  611. ) {
  612. // Templates management
  613. $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
  614. $sql = "SELECT id FROM $table_template
  615. WHERE
  616. course_code = '".$_course['code']."' AND
  617. user_id = '".api_get_user_id()."' AND
  618. ref_doc = '".$row['id']."'";
  619. $template_result = Database::query($sql);
  620. $row['is_template'] = (Database::num_rows($template_result) > 0) ? 1 : 0;
  621. }
  622. $row['basename'] = basename($row['path']);
  623. // Just filling $document_data.
  624. $document_data[$row['id']] = $row;
  625. }
  626. // Only for the student we filter the results see BT#1652
  627. if (!$isCoach && !$is_allowed_to_edit) {
  628. $ids_to_remove = array();
  629. $my_repeat_ids = $temp = array();
  630. // Selecting repeated ids
  631. foreach ($doc_list as $row) {
  632. if (in_array($row['id'], array_keys($temp))) {
  633. $my_repeat_ids[] = $row['id'];
  634. }
  635. $temp[$row['id']] = $row;
  636. }
  637. //@todo use the self::is_visible function
  638. // Checking visibility in a session
  639. foreach ($my_repeat_ids as $id) {
  640. foreach ($doc_list as $row) {
  641. if ($id == $row['id']) {
  642. if ($row['visibility'] == 0 && $row['item_property_session_id'] == 0) {
  643. $delete_repeated[$id] = true;
  644. }
  645. if ($row['visibility'] == 0 && $row['item_property_session_id'] != 0) {
  646. $delete_repeated[$id] = true;
  647. }
  648. }
  649. }
  650. }
  651. foreach ($doc_list as $key => $row) {
  652. if (in_array($row['visibility'], array('0', '2')) &&
  653. !in_array($row['id'], $my_repeat_ids)
  654. ) {
  655. $ids_to_remove[] = $row['id'];
  656. unset($doc_list[$key]);
  657. }
  658. }
  659. foreach ($document_data as $row) {
  660. if (in_array($row['id'], $ids_to_remove)) {
  661. unset($document_data[$row['id']]);
  662. }
  663. if (isset($delete_repeated[$row['id']]) && $delete_repeated[$row['id']]) {
  664. unset($document_data[$row['id']]);
  665. }
  666. }
  667. // Checking parents visibility.
  668. $final_document_data = array();
  669. foreach ($document_data as $row) {
  670. $is_visible = self::check_visibility_tree(
  671. $row['id'],
  672. $_course['code'],
  673. $sessionId,
  674. api_get_user_id(),
  675. $to_group_id
  676. );
  677. if ($is_visible) {
  678. $final_document_data[$row['id']] = $row;
  679. }
  680. }
  681. } else {
  682. $final_document_data = $document_data;
  683. }
  684. return $final_document_data;
  685. } else {
  686. return false;
  687. }
  688. }
  689. /**
  690. * Gets the paths of all folders in a course
  691. * can show all folders (except for the deleted ones) or only visible ones
  692. *
  693. * @param array $_course
  694. * @param int $groupIid iid
  695. * @param boolean $can_see_invisible
  696. * @param boolean $getInvisibleList
  697. * @param string $path current path
  698. *
  699. * @return array with paths
  700. */
  701. public static function get_all_document_folders(
  702. $_course,
  703. $groupIid = 0,
  704. $can_see_invisible = false,
  705. $getInvisibleList = false,
  706. $path = ''
  707. ) {
  708. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  709. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  710. $groupIid = intval($groupIid);
  711. $document_folders = array();
  712. $students = CourseManager::get_user_list_from_course_code(
  713. $_course['code'],
  714. api_get_session_id()
  715. );
  716. $conditionList = array();
  717. if (!empty($students)) {
  718. foreach ($students as $studentId => $studentInfo) {
  719. $conditionList[] = '/shared_folder/sf_user_'.$studentInfo['user_id'];
  720. }
  721. }
  722. $groupCondition = " last.to_group_id = $groupIid";
  723. if (empty($groupIid)) {
  724. $groupCondition = " (last.to_group_id = 0 OR last.to_group_id IS NULL)";
  725. }
  726. $show_users_condition = '';
  727. if (api_get_setting('show_users_folders') === 'false') {
  728. $show_users_condition = " AND docs.path NOT LIKE '%shared_folder%'";
  729. }
  730. if ($can_see_invisible) {
  731. // condition for the session
  732. $session_id = api_get_session_id();
  733. //$condition_session = api_get_session_condition($session_id, true, false, 'docs.session_id');
  734. $session_id = $session_id ?: api_get_session_id();
  735. $condition_session = " AND (last.session_id = '$session_id' OR (last.session_id = '0' OR last.session_id IS NULL) )";
  736. $condition_session .= self::getSessionFolderFilters($path, $session_id);
  737. if ($groupIid <> 0) {
  738. $sql = "SELECT DISTINCT docs.id, path
  739. FROM $TABLE_ITEMPROPERTY AS last
  740. INNER JOIN $TABLE_DOCUMENT AS docs
  741. ON (
  742. docs.id = last.ref AND
  743. docs.c_id = last.c_id
  744. )
  745. WHERE
  746. last.tool = '".TOOL_DOCUMENT."' AND
  747. last.c_id = {$_course['real_id']} AND
  748. docs.c_id = {$_course['real_id']} AND
  749. docs.filetype = 'folder' AND
  750. $groupCondition AND
  751. docs.path NOT LIKE '%shared_folder%' AND
  752. docs.path NOT LIKE '%_DELETED_%' AND
  753. last.visibility <> 2
  754. $condition_session ";
  755. } else {
  756. $sql = "SELECT DISTINCT docs.id, path
  757. FROM $TABLE_ITEMPROPERTY AS last
  758. INNER JOIN $TABLE_DOCUMENT AS docs
  759. ON (
  760. docs.id = last.ref AND
  761. docs.c_id = last.c_id
  762. )
  763. WHERE
  764. last.tool = '".TOOL_DOCUMENT."' AND
  765. last.c_id = {$_course['real_id']} AND
  766. docs.c_id = {$_course['real_id']} AND
  767. docs.filetype = 'folder' AND
  768. docs.path NOT LIKE '%_DELETED_%' AND
  769. $groupCondition AND
  770. last.visibility <> 2
  771. $show_users_condition
  772. $condition_session
  773. ";
  774. }
  775. $result = Database::query($sql);
  776. if ($result && Database::num_rows($result) != 0) {
  777. while ($row = Database::fetch_array($result, 'ASSOC')) {
  778. if (self::is_folder_to_avoid($row['path'])) {
  779. continue;
  780. }
  781. if (strpos($row['path'], '/shared_folder/') !== false) {
  782. if (!in_array($row['path'], $conditionList)) {
  783. continue;
  784. }
  785. }
  786. $document_folders[$row['id']] = $row['path'];
  787. }
  788. if (!empty($document_folders)) {
  789. natsort($document_folders);
  790. }
  791. return $document_folders;
  792. } else {
  793. return false;
  794. }
  795. } else {
  796. // No invisible folders
  797. // Condition for the session
  798. $session_id = api_get_session_id();
  799. $condition_session = api_get_session_condition(
  800. $session_id,
  801. true,
  802. false,
  803. 'docs.session_id'
  804. );
  805. $visibilityCondition = 'last.visibility = 1';
  806. $fileType = "docs.filetype = 'folder' AND";
  807. if ($getInvisibleList) {
  808. $visibilityCondition = 'last.visibility = 0';
  809. $fileType = '';
  810. }
  811. //get visible folders
  812. $sql = "SELECT DISTINCT docs.id, path
  813. FROM
  814. $TABLE_ITEMPROPERTY AS last
  815. INNER JOIN $TABLE_DOCUMENT AS docs
  816. ON (docs.id = last.ref AND last.c_id = docs.c_id)
  817. WHERE
  818. $fileType
  819. last.tool = '".TOOL_DOCUMENT."' AND
  820. $groupCondition AND
  821. $visibilityCondition
  822. $show_users_condition
  823. $condition_session AND
  824. last.c_id = {$_course['real_id']} AND
  825. docs.c_id = {$_course['real_id']} ";
  826. $result = Database::query($sql);
  827. $visibleFolders = array();
  828. while ($row = Database::fetch_array($result, 'ASSOC')) {
  829. $visibleFolders[$row['id']] = $row['path'];
  830. }
  831. if ($getInvisibleList) {
  832. return $visibleFolders;
  833. }
  834. //get invisible folders
  835. $sql = "SELECT DISTINCT docs.id, path
  836. FROM $TABLE_ITEMPROPERTY AS last
  837. INNER JOIN $TABLE_DOCUMENT AS docs
  838. ON (docs.id = last.ref AND last.c_id = docs.c_id)
  839. WHERE
  840. docs.filetype = 'folder' AND
  841. last.tool = '".TOOL_DOCUMENT."' AND
  842. $groupCondition AND
  843. last.visibility = 0 $condition_session AND
  844. last.c_id = {$_course['real_id']} AND
  845. docs.c_id = {$_course['real_id']} ";
  846. $result = Database::query($sql);
  847. $invisibleFolders = array();
  848. while ($row = Database::fetch_array($result, 'ASSOC')) {
  849. //get visible folders in the invisible ones -> they are invisible too
  850. $sql = "SELECT DISTINCT docs.id, path
  851. FROM $TABLE_ITEMPROPERTY AS last
  852. INNER JOIN $TABLE_DOCUMENT AS docs
  853. ON (docs.id = last.ref AND docs.c_id = last.c_id)
  854. WHERE
  855. docs.path LIKE '".Database::escape_string($row['path'].'/%')."' AND
  856. docs.filetype = 'folder' AND
  857. last.tool = '" . TOOL_DOCUMENT."' AND
  858. $groupCondition AND
  859. last.visibility = 1 $condition_session AND
  860. last.c_id = {$_course['real_id']} AND
  861. docs.c_id = {$_course['real_id']} ";
  862. $folder_in_invisible_result = Database::query($sql);
  863. while ($folders_in_invisible_folder = Database::fetch_array($folder_in_invisible_result, 'ASSOC')) {
  864. $invisibleFolders[$folders_in_invisible_folder['id']] = $folders_in_invisible_folder['path'];
  865. }
  866. }
  867. // If both results are arrays -> //calculate the difference between the 2 arrays -> only visible folders are left :)
  868. if (is_array($visibleFolders) && is_array($invisibleFolders)) {
  869. $document_folders = array_diff($visibleFolders, $invisibleFolders);
  870. natsort($document_folders);
  871. return $document_folders;
  872. } elseif (is_array($visibleFolders)) {
  873. natsort($visibleFolders);
  874. return $visibleFolders;
  875. } else {
  876. //no visible folders found
  877. return false;
  878. }
  879. }
  880. }
  881. /**
  882. * This check if a document has the readonly property checked, then see if the user
  883. * is the owner of this file, if all this is true then return true.
  884. *
  885. * @param array $_course
  886. * @param int $user_id id of the current user
  887. * @param string $file path stored in the database (if not defined, $documentId must be used)
  888. * @param int $document_id in case you dont have the file path ,
  889. * insert the id of the file here and leave $file in blank ''
  890. * @param bool $to_delete
  891. * @param int $sessionId
  892. * @return boolean true/false
  893. * */
  894. public static function check_readonly(
  895. $_course,
  896. $user_id,
  897. $file = null,
  898. $document_id = '',
  899. $to_delete = false,
  900. $sessionId = null,
  901. $documentId = null
  902. ) {
  903. if (empty($sessionId)) {
  904. $sessionId = api_get_session_id();
  905. } else {
  906. $sessionId = intval($sessionId);
  907. }
  908. if (empty($document_id) || !is_numeric($document_id)) {
  909. $document_id = self::get_document_id($_course, $file, $sessionId);
  910. } else {
  911. $document_id = intval($document_id);
  912. }
  913. $TABLE_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  914. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  915. $course_id = $_course['real_id'];
  916. if ($to_delete) {
  917. if (self::is_folder($_course, $document_id)) {
  918. if (!empty($file)) {
  919. $path = Database::escape_string($file);
  920. // Check
  921. $sql = "SELECT td.id, readonly, tp.insert_user_id
  922. FROM $TABLE_DOCUMENT td
  923. INNER JOIN $TABLE_PROPERTY tp
  924. ON (td.c_id = tp.c_id AND tp.ref= td.id)
  925. WHERE
  926. td.c_id = $course_id AND
  927. tp.c_id = $course_id AND
  928. td.session_id = $sessionId AND
  929. (path='".$path."' OR path LIKE BINARY '".$path."/%' ) ";
  930. // Get all id's of documents that are deleted
  931. $what_to_check_result = Database::query($sql);
  932. if ($what_to_check_result && Database::num_rows($what_to_check_result) != 0) {
  933. // file with readonly set to 1 exist?
  934. $readonly_set = false;
  935. while ($row = Database::fetch_array($what_to_check_result)) {
  936. //query to delete from item_property table
  937. if ($row['readonly'] == 1) {
  938. if (!($row['insert_user_id'] == $user_id)) {
  939. $readonly_set = true;
  940. break;
  941. }
  942. }
  943. }
  944. if ($readonly_set) {
  945. return true;
  946. }
  947. }
  948. }
  949. return false;
  950. }
  951. }
  952. if (!empty($document_id)) {
  953. $sql = "SELECT a.insert_user_id, b.readonly
  954. FROM $TABLE_PROPERTY a
  955. INNER JOIN $TABLE_DOCUMENT b
  956. ON (a.c_id = b.c_id AND a.ref= b.id)
  957. WHERE
  958. a.c_id = $course_id AND
  959. b.c_id = $course_id AND
  960. a.ref = $document_id
  961. LIMIT 1";
  962. $result = Database::query($sql);
  963. $doc_details = Database::fetch_array($result, 'ASSOC');
  964. if ($doc_details['readonly'] == 1) {
  965. return !($doc_details['insert_user_id'] == $user_id || api_is_platform_admin());
  966. }
  967. }
  968. return false;
  969. }
  970. /**
  971. * This check if a document is a folder or not
  972. * @param array $_course
  973. * @param int $document_id of the item
  974. * @return boolean true/false
  975. * */
  976. public static function is_folder($_course, $document_id)
  977. {
  978. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  979. $course_id = $_course['real_id'];
  980. $document_id = intval($document_id);
  981. $sql = "SELECT filetype FROM $TABLE_DOCUMENT
  982. WHERE c_id = $course_id AND id= $document_id";
  983. $result = Database::fetch_array(Database::query($sql), 'ASSOC');
  984. return $result['filetype'] == 'folder';
  985. }
  986. /**
  987. * @param int $document_id
  988. * @param array $course_info
  989. * @param int $session_id
  990. * @param bool $remove_content_from_db
  991. */
  992. public static function deleteDocumentFromDb(
  993. $document_id,
  994. $course_info = array(),
  995. $session_id = 0,
  996. $remove_content_from_db = false
  997. ) {
  998. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  999. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  1000. // Deleting from the DB
  1001. $user_id = api_get_user_id();
  1002. $document_id = intval($document_id);
  1003. if (empty($course_info)) {
  1004. $course_info = api_get_course_info();
  1005. }
  1006. if (empty($session_id)) {
  1007. $session_id = api_get_session_id();
  1008. }
  1009. // Soft DB delete
  1010. api_item_property_update(
  1011. $course_info,
  1012. TOOL_DOCUMENT,
  1013. $document_id,
  1014. 'delete',
  1015. $user_id,
  1016. null,
  1017. null,
  1018. null,
  1019. null,
  1020. $session_id
  1021. );
  1022. self::delete_document_from_search_engine($course_info['code'], $document_id);
  1023. self::unset_document_as_template($document_id, $course_info['code'], $user_id);
  1024. //Hard DB delete
  1025. if ($remove_content_from_db) {
  1026. $sql = "DELETE FROM $TABLE_ITEMPROPERTY
  1027. WHERE
  1028. c_id = {$course_info['real_id']} AND
  1029. ref = ".$document_id." AND
  1030. tool='".TOOL_DOCUMENT."'";
  1031. Database::query($sql);
  1032. $sql = "DELETE FROM $TABLE_DOCUMENT
  1033. WHERE c_id = {$course_info['real_id']} AND id = ".$document_id;
  1034. Database::query($sql);
  1035. }
  1036. }
  1037. /**
  1038. * This deletes a document by changing visibility to 2, renaming it to filename_DELETED_#id
  1039. * Files/folders that are inside a deleted folder get visibility 2
  1040. *
  1041. * @param array $_course
  1042. * @param string $path, path stored in the database
  1043. * @param string $base_work_dir, path to the documents folder (if not defined, $documentId must be used)
  1044. * @param int $sessionId The ID of the session, if any
  1045. * @param int $documentId The document id, if available
  1046. * @param int $groupId iid
  1047. * @return boolean true/false
  1048. * @todo now only files/folders in a folder get visibility 2, we should rename them too.
  1049. * @todo We should be able to get rid of this later when using only documentId (check further usage)
  1050. */
  1051. public static function delete_document(
  1052. $_course,
  1053. $path = null,
  1054. $base_work_dir = null,
  1055. $sessionId = null,
  1056. $documentId = null,
  1057. $groupId = 0
  1058. ) {
  1059. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  1060. if (empty($groupId)) {
  1061. $groupId = api_get_group_id();
  1062. } else {
  1063. $groupId = intval($groupId);
  1064. }
  1065. if (empty($sessionId)) {
  1066. $sessionId = api_get_session_id();
  1067. } else {
  1068. $sessionId = intval($sessionId);
  1069. }
  1070. $course_id = $_course['real_id'];
  1071. if (empty($course_id)) {
  1072. return false;
  1073. }
  1074. if (empty($base_work_dir)) {
  1075. return false;
  1076. }
  1077. if (empty($documentId)) {
  1078. $documentId = self::get_document_id($_course, $path, $sessionId);
  1079. $docInfo = self::get_document_data_by_id(
  1080. $documentId,
  1081. $_course['code'],
  1082. false,
  1083. $sessionId
  1084. );
  1085. $path = $docInfo['path'];
  1086. } else {
  1087. $docInfo = self::get_document_data_by_id(
  1088. $documentId,
  1089. $_course['code'],
  1090. false,
  1091. $sessionId
  1092. );
  1093. if (empty($docInfo)) {
  1094. return false;
  1095. }
  1096. $path = $docInfo['path'];
  1097. }
  1098. $documentId = intval($documentId);
  1099. if (empty($path) || empty($docInfo) || empty($documentId)) {
  1100. return false;
  1101. }
  1102. $itemInfo = api_get_item_property_info(
  1103. $_course['real_id'],
  1104. TOOL_DOCUMENT,
  1105. $documentId,
  1106. $sessionId,
  1107. $groupId
  1108. );
  1109. if (empty($itemInfo)) {
  1110. return false;
  1111. }
  1112. // File was already deleted.
  1113. if ($itemInfo['lastedit_type'] == 'DocumentDeleted' ||
  1114. $itemInfo['lastedit_type'] == 'delete' ||
  1115. $itemInfo['visibility'] == 2
  1116. ) {
  1117. return false;
  1118. }
  1119. // Filtering by group.
  1120. if ($itemInfo['to_group_id'] != $groupId) {
  1121. return false;
  1122. }
  1123. $document_exists_in_disk = file_exists($base_work_dir.$path);
  1124. $new_path = $path.'_DELETED_'.$documentId;
  1125. $file_deleted_from_db = false;
  1126. $file_deleted_from_disk = false;
  1127. $file_renamed_from_disk = false;
  1128. if ($documentId) {
  1129. // Deleting doc from the DB.
  1130. self::deleteDocumentFromDb($documentId, $_course, $sessionId);
  1131. // Checking
  1132. // $file_exists_in_db = self::get_document_data_by_id($documentId, $_course['code']);
  1133. $file_deleted_from_db = true;
  1134. }
  1135. // Looking for children.
  1136. if ($docInfo['filetype'] == 'folder') {
  1137. $cleanPath = Database::escape_string($path);
  1138. // Deleted files inside this folder.
  1139. $sql = "SELECT id FROM $TABLE_DOCUMENT
  1140. WHERE
  1141. c_id = $course_id AND
  1142. session_id = $sessionId AND
  1143. path LIKE BINARY '".$cleanPath."/%'";
  1144. // Get all id's of documents that are deleted.
  1145. $result = Database::query($sql);
  1146. if ($result && Database::num_rows($result) != 0) {
  1147. // Recursive delete.
  1148. while ($row = Database::fetch_array($result)) {
  1149. self::delete_document(
  1150. $_course,
  1151. null,
  1152. $base_work_dir,
  1153. $sessionId,
  1154. $row['id'],
  1155. $groupId
  1156. );
  1157. }
  1158. }
  1159. }
  1160. if ($document_exists_in_disk) {
  1161. if (api_get_setting('permanently_remove_deleted_files') === 'true') {
  1162. // Delete documents, do it like this so metadata gets deleted too
  1163. my_delete($base_work_dir.$path);
  1164. // Hard delete.
  1165. self::deleteDocumentFromDb($documentId, $_course, $sessionId, true);
  1166. $file_deleted_from_disk = true;
  1167. } else {
  1168. // Set visibility to 2 and rename file/folder to xxx_DELETED_#id (soft delete)
  1169. if (is_file($base_work_dir.$path) || is_dir($base_work_dir.$path)) {
  1170. if (rename($base_work_dir.$path, $base_work_dir.$new_path)) {
  1171. $new_path = Database::escape_string($new_path);
  1172. $sql = "UPDATE $TABLE_DOCUMENT
  1173. SET path = '".$new_path."'
  1174. WHERE
  1175. c_id = $course_id AND
  1176. session_id = $sessionId AND
  1177. id = ".$documentId;
  1178. Database::query($sql);
  1179. // Soft delete.
  1180. self::deleteDocumentFromDb($documentId, $_course, $sessionId);
  1181. // Change path of sub folders and documents in database.
  1182. $old_item_path = $docInfo['path'];
  1183. $new_item_path = $new_path.substr($old_item_path, strlen($path));
  1184. $new_item_path = Database::escape_string($new_item_path);
  1185. $sql = "UPDATE $TABLE_DOCUMENT
  1186. SET path = '".$new_item_path."'
  1187. WHERE
  1188. c_id = $course_id AND
  1189. session_id = $sessionId AND
  1190. id = ".$documentId;
  1191. Database::query($sql);
  1192. $file_renamed_from_disk = true;
  1193. } else {
  1194. // Couldn't rename - file permissions problem?
  1195. error_log(
  1196. __FILE__.' '.__LINE__.': Error renaming '.$base_work_dir.$path.' to '.$base_work_dir.$new_path.'. This is probably due to file permissions',
  1197. 0
  1198. );
  1199. }
  1200. }
  1201. }
  1202. }
  1203. // Checking inconsistency
  1204. //error_log('Doc status: (1 del db :'.($file_deleted_from_db?'yes':'no').') - (2 del disk: '.($file_deleted_from_disk?'yes':'no').') - (3 ren disk: '.($file_renamed_from_disk?'yes':'no').')');
  1205. if ($file_deleted_from_db && $file_deleted_from_disk ||
  1206. $file_deleted_from_db && $file_renamed_from_disk
  1207. ) {
  1208. return true;
  1209. } else {
  1210. //Something went wrong
  1211. //The file or directory isn't there anymore (on the filesystem)
  1212. // This means it has been removed externally. To prevent a
  1213. // blocking error from happening, we drop the related items from the
  1214. // item_property and the document table.
  1215. error_log(
  1216. __FILE__.' '.__LINE__.': System inconsistency detected. The file or directory '.$base_work_dir.$path.' seems to have been removed from the filesystem independently from the web platform. To restore consistency, the elements using the same path will be removed from the database',
  1217. 0
  1218. );
  1219. return false;
  1220. }
  1221. }
  1222. /**
  1223. * Removes documents from search engine database
  1224. *
  1225. * @param string $course_id Course code
  1226. * @param int $document_id Document id to delete
  1227. */
  1228. public static function delete_document_from_search_engine($course_id, $document_id)
  1229. {
  1230. // remove from search engine if enabled
  1231. if (api_get_setting('search_enabled') === 'true') {
  1232. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  1233. $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  1234. $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
  1235. $res = Database::query($sql);
  1236. if (Database::num_rows($res) > 0) {
  1237. $row2 = Database::fetch_array($res);
  1238. require_once api_get_path(LIBRARY_PATH).'search/ChamiloIndexer.class.php';
  1239. $di = new ChamiloIndexer();
  1240. $di->remove_document((int) $row2['search_did']);
  1241. }
  1242. $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  1243. $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
  1244. Database::query($sql);
  1245. // remove terms from db
  1246. require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
  1247. delete_all_values_for_item($course_id, TOOL_DOCUMENT, $document_id);
  1248. }
  1249. }
  1250. /**
  1251. * Gets the id of a document with a given path
  1252. *
  1253. * @param array $courseInfo
  1254. * @param string $path
  1255. * @param int $sessionId
  1256. * @return int id of document / false if no doc found
  1257. */
  1258. public static function get_document_id($courseInfo, $path, $sessionId = null)
  1259. {
  1260. $table = Database::get_course_table(TABLE_DOCUMENT);
  1261. $courseId = $courseInfo['real_id'];
  1262. if (!isset($sessionId)) {
  1263. $sessionId = api_get_session_id();
  1264. } else {
  1265. $sessionId = intval($sessionId);
  1266. }
  1267. $path = Database::escape_string($path);
  1268. if (!empty($courseId) && !empty($path)) {
  1269. $sql = "SELECT id FROM $table
  1270. WHERE
  1271. c_id = $courseId AND
  1272. path LIKE BINARY '$path' AND
  1273. session_id = $sessionId
  1274. LIMIT 1";
  1275. $result = Database::query($sql);
  1276. if (Database::num_rows($result)) {
  1277. $row = Database::fetch_array($result);
  1278. return intval($row['id']);
  1279. }
  1280. }
  1281. return false;
  1282. }
  1283. /**
  1284. * Gets the document data with a given id
  1285. *
  1286. * @param int $id Document Id (id field in c_document table)
  1287. * @param string $course_code Course code
  1288. * @param bool $load_parents load folder parents.
  1289. * @param int $session_id The session ID,
  1290. * 0 if requires context *out of* session, and null to use global context
  1291. * @return array document content
  1292. */
  1293. public static function get_document_data_by_id(
  1294. $id,
  1295. $course_code,
  1296. $load_parents = false,
  1297. $session_id = null
  1298. ) {
  1299. $course_info = api_get_course_info($course_code);
  1300. $course_id = $course_info['real_id'];
  1301. if (empty($course_info)) {
  1302. return false;
  1303. }
  1304. $session_id = empty($session_id) ? api_get_session_id() : intval($session_id);
  1305. $www = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/document';
  1306. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  1307. $id = intval($id);
  1308. $sessionCondition = api_get_session_condition($session_id, true, true);
  1309. $sql = "SELECT * FROM $TABLE_DOCUMENT
  1310. WHERE c_id = $course_id $sessionCondition AND id = $id";
  1311. $result = Database::query($sql);
  1312. if ($result && Database::num_rows($result) == 1) {
  1313. $row = Database::fetch_array($result, 'ASSOC');
  1314. //@todo need to clarify the name of the URLs not nice right now
  1315. $url_path = urlencode($row['path']);
  1316. $path = str_replace('%2F', '/', $url_path);
  1317. $pathinfo = pathinfo($row['path']);
  1318. $row['url'] = api_get_path(WEB_CODE_PATH).'document/showinframes.php?cidReq='.$course_code.'&id='.$id;
  1319. $row['document_url'] = api_get_path(WEB_CODE_PATH).'document/document.php?cidReq='.$course_code.'&id='.$id;
  1320. $row['absolute_path'] = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$row['path'];
  1321. $row['absolute_path_from_document'] = '/document'.$row['path'];
  1322. $row['absolute_parent_path'] = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$pathinfo['dirname'].'/';
  1323. $row['direct_url'] = $www.$path;
  1324. $row['basename'] = basename($row['path']);
  1325. if (dirname($row['path']) == '.') {
  1326. $row['parent_id'] = '0';
  1327. } else {
  1328. $row['parent_id'] = self::get_document_id($course_info, dirname($row['path']), $session_id);
  1329. }
  1330. $parents = array();
  1331. //Use to generate parents (needed for the breadcrumb)
  1332. //@todo sorry but this for is here because there's not a parent_id in the document table so we parsed the path!!
  1333. if ($load_parents) {
  1334. $dir_array = explode('/', $row['path']);
  1335. $dir_array = array_filter($dir_array);
  1336. $array_len = count($dir_array) + 1;
  1337. $real_dir = '';
  1338. for ($i = 1; $i < $array_len; $i++) {
  1339. $real_dir .= '/'.(isset($dir_array[$i]) ? $dir_array[$i] : '');
  1340. $parent_id = self::get_document_id($course_info, $real_dir);
  1341. if ($session_id != 0 && empty($parent_id)) {
  1342. $parent_id = self::get_document_id($course_info, $real_dir, 0);
  1343. }
  1344. if (!empty($parent_id)) {
  1345. $sub_document_data = self::get_document_data_by_id(
  1346. $parent_id,
  1347. $course_code,
  1348. false,
  1349. $session_id
  1350. );
  1351. if ($session_id != 0 and !$sub_document_data) {
  1352. $sub_document_data = self::get_document_data_by_id(
  1353. $parent_id,
  1354. $course_code,
  1355. false,
  1356. 0
  1357. );
  1358. }
  1359. //@todo add visibility here
  1360. $parents[] = $sub_document_data;
  1361. }
  1362. }
  1363. }
  1364. $row['parents'] = $parents;
  1365. return $row;
  1366. }
  1367. return false;
  1368. }
  1369. /**
  1370. * Allow to set a specific document as a new template for CKeditor
  1371. * for a particular user in a particular course
  1372. *
  1373. * @param string $title
  1374. * @param string $description
  1375. * @param int $document_id_for_template the document id
  1376. * @param string $course_code
  1377. * @param int $user_id
  1378. * @return bool
  1379. */
  1380. public static function set_document_as_template($title, $description, $document_id_for_template, $course_code, $user_id, $image)
  1381. {
  1382. // Database table definition
  1383. $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
  1384. $params = [
  1385. 'title' => $title,
  1386. 'description' => $description,
  1387. 'course_code' => $course_code,
  1388. 'user_id' => $user_id,
  1389. 'ref_doc' => $document_id_for_template,
  1390. 'image' => $image,
  1391. ];
  1392. Database::insert($table_template, $params);
  1393. return true;
  1394. }
  1395. /**
  1396. * Unset a document as template
  1397. *
  1398. * @param int $document_id
  1399. * @param string $course_code
  1400. * @param int $user_id
  1401. */
  1402. public static function unset_document_as_template($document_id, $course_code, $user_id)
  1403. {
  1404. $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
  1405. $course_code = Database::escape_string($course_code);
  1406. $user_id = intval($user_id);
  1407. $document_id = intval($document_id);
  1408. $sql = 'SELECT id FROM '.$table_template.'
  1409. WHERE
  1410. course_code="' . $course_code.'" AND
  1411. user_id="' . $user_id.'" AND
  1412. ref_doc="' . $document_id.'"';
  1413. $result = Database::query($sql);
  1414. $template_id = Database::result($result, 0, 0);
  1415. my_delete(api_get_path(SYS_CODE_PATH).'upload/template_thumbnails/'.$template_id.'.jpg');
  1416. $sql = 'DELETE FROM '.$table_template.'
  1417. WHERE
  1418. course_code="' . $course_code.'" AND
  1419. user_id="' . $user_id.'" AND
  1420. ref_doc="' . $document_id.'"';
  1421. Database::query($sql);
  1422. }
  1423. /**
  1424. * Return true if the documentpath have visibility=1 as
  1425. * item_property (you should use the is_visible_by_id)
  1426. *
  1427. * @param string $document_path the relative complete path of the document
  1428. * @param array $course the _course array info of the document's course
  1429. * @param int
  1430. * @param string
  1431. * @return bool
  1432. */
  1433. public static function is_visible($doc_path, $course, $session_id = 0, $file_type = 'file')
  1434. {
  1435. $docTable = Database::get_course_table(TABLE_DOCUMENT);
  1436. $propTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
  1437. $course_id = $course['real_id'];
  1438. //note the extra / at the end of doc_path to match every path in the document table that is part of the document path
  1439. $session_id = intval($session_id);
  1440. $condition = "AND d.session_id IN ('$session_id', '0') ";
  1441. // The " d.filetype='file' " let the user see a file even if the folder is hidden see #2198
  1442. /*
  1443. When using hotpotatoes files, a new html files are generated
  1444. in the hotpotatoes folder to display the test.
  1445. The genuine html file is copied to math4.htm(user_id).t.html
  1446. Images files are not copied, and keep same name.
  1447. To check the html file visibility, we don't have to check file math4.htm(user_id).t.html but file math4.htm
  1448. In this case, we have to remove (user_id).t.html to check the visibility of the file
  1449. For images, we just check the path of the image file.
  1450. Exemple of hotpotatoes folder :
  1451. A.jpg
  1452. maths4-consigne.jpg
  1453. maths4.htm
  1454. maths4.htm1.t.html
  1455. maths4.htm52.t.html
  1456. maths4.htm654.t.html
  1457. omega.jpg
  1458. theta.jpg
  1459. */
  1460. if (strpos($doc_path, 'HotPotatoes_files') && preg_match("/\.t\.html$/", $doc_path)) {
  1461. $doc_path = substr($doc_path, 0, strlen($doc_path) - 7 - strlen(api_get_user_id()));
  1462. }
  1463. if (!in_array($file_type, array('file', 'folder'))) {
  1464. $file_type = 'file';
  1465. }
  1466. $doc_path = Database::escape_string($doc_path).'/';
  1467. $sql = "SELECT visibility
  1468. FROM $docTable d
  1469. INNER JOIN $propTable ip
  1470. ON (d.id = ip.ref AND d.c_id = ip.c_id)
  1471. WHERE
  1472. d.c_id = $course_id AND
  1473. ip.c_id = $course_id AND
  1474. ip.tool = '".TOOL_DOCUMENT."' $condition AND
  1475. filetype = '$file_type' AND
  1476. locate(concat(path,'/'), '$doc_path')=1
  1477. ";
  1478. $result = Database::query($sql);
  1479. $is_visible = false;
  1480. if (Database::num_rows($result) > 0) {
  1481. $row = Database::fetch_array($result, 'ASSOC');
  1482. if ($row['visibility'] == 1) {
  1483. $is_visible = api_is_allowed_in_course() || api_is_platform_admin();
  1484. }
  1485. }
  1486. /* improved protection of documents viewable directly through the url:
  1487. incorporates the same protections of the course at the url of
  1488. documents:
  1489. access allowed for the whole world Open, access allowed for
  1490. users registered on the platform Private access, document accessible
  1491. only to course members (see the Users list), Completely closed;
  1492. the document is only accessible to the course admin and
  1493. teaching assistants.*/
  1494. //return $_SESSION ['is_allowed_in_course'] || api_is_platform_admin();
  1495. return $is_visible;
  1496. }
  1497. /**
  1498. * Return true if user can see a file
  1499. *
  1500. * @param int document id
  1501. * @param array course info
  1502. * @param int
  1503. * @param int
  1504. * @param bool
  1505. * @return bool
  1506. */
  1507. public static function is_visible_by_id(
  1508. $doc_id,
  1509. $course_info,
  1510. $session_id,
  1511. $user_id,
  1512. $admins_can_see_everything = true,
  1513. $userIsSubscribed = null
  1514. ) {
  1515. $user_in_course = false;
  1516. //1. Checking the course array
  1517. if (empty($course_info)) {
  1518. $course_info = api_get_course_info();
  1519. if (empty($course_info)) {
  1520. return false;
  1521. }
  1522. }
  1523. $doc_id = intval($doc_id);
  1524. $session_id = intval($session_id);
  1525. //2. Course and Session visibility are handle in local.inc.php/global.inc.php
  1526. //3. Checking if user exist in course/session
  1527. if ($session_id == 0) {
  1528. if (is_null($userIsSubscribed)) {
  1529. $userIsSubscribed = CourseManager::is_user_subscribed_in_course(
  1530. $user_id,
  1531. $course_info['code']
  1532. );
  1533. }
  1534. if ($userIsSubscribed === true || api_is_platform_admin()) {
  1535. $user_in_course = true;
  1536. }
  1537. // Check if course is open then we can consider that the student is registered to the course
  1538. if (isset($course_info) &&
  1539. in_array(
  1540. $course_info['visibility'],
  1541. array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD)
  1542. )
  1543. ) {
  1544. $user_in_course = true;
  1545. }
  1546. } else {
  1547. $user_status = SessionManager::get_user_status_in_course_session(
  1548. $user_id,
  1549. $course_info['real_id'],
  1550. $session_id
  1551. );
  1552. if (in_array($user_status, array('0', '2', '6'))) {
  1553. //is true if is an student, course session teacher or coach
  1554. $user_in_course = true;
  1555. }
  1556. if (api_is_platform_admin()) {
  1557. $user_in_course = true;
  1558. }
  1559. }
  1560. // 4. Checking document visibility (i'm repeating the code in order to be more clear when reading ) - jm
  1561. if ($user_in_course) {
  1562. // 4.1 Checking document visibility for a Course
  1563. if ($session_id == 0) {
  1564. $item_info = api_get_item_property_info(
  1565. $course_info['real_id'],
  1566. 'document',
  1567. $doc_id,
  1568. 0
  1569. );
  1570. if (isset($item_info['visibility'])) {
  1571. // True for admins if document exists
  1572. if ($admins_can_see_everything && api_is_platform_admin()) {
  1573. return true;
  1574. }
  1575. if ($item_info['visibility'] == 1) {
  1576. return true;
  1577. }
  1578. }
  1579. } else {
  1580. // 4.2 Checking document visibility for a Course in a Session
  1581. $item_info = api_get_item_property_info(
  1582. $course_info['real_id'],
  1583. 'document',
  1584. $doc_id,
  1585. 0
  1586. );
  1587. $item_info_in_session = api_get_item_property_info(
  1588. $course_info['real_id'],
  1589. 'document',
  1590. $doc_id,
  1591. $session_id
  1592. );
  1593. // True for admins if document exists
  1594. if (isset($item_info['visibility'])) {
  1595. if ($admins_can_see_everything && api_is_platform_admin()) {
  1596. return true;
  1597. }
  1598. }
  1599. if (isset($item_info_in_session['visibility'])) {
  1600. if ($item_info_in_session['visibility'] == 1) {
  1601. return true;
  1602. }
  1603. } else {
  1604. if ($item_info['visibility'] == 1) {
  1605. return true;
  1606. }
  1607. }
  1608. }
  1609. } elseif ($admins_can_see_everything && api_is_platform_admin()) {
  1610. return true;
  1611. }
  1612. return false;
  1613. }
  1614. /**
  1615. * Allow attach a certificate to a course
  1616. * @param string $course_id
  1617. * @param int $document_id
  1618. * @param int $session_id
  1619. * @return void
  1620. */
  1621. public static function attach_gradebook_certificate($course_id, $document_id, $session_id = 0)
  1622. {
  1623. $tbl_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1624. $session_id = intval($session_id);
  1625. if (empty($session_id)) {
  1626. $session_id = api_get_session_id();
  1627. }
  1628. if (empty($session_id)) {
  1629. $sql_session = 'AND (session_id = 0 OR isnull(session_id)) ';
  1630. } elseif ($session_id > 0) {
  1631. $sql_session = 'AND session_id='.intval($session_id);
  1632. } else {
  1633. $sql_session = '';
  1634. }
  1635. $sql = 'UPDATE '.$tbl_category.' SET document_id="'.intval($document_id).'"
  1636. WHERE course_code="' . Database::escape_string($course_id).'" '.$sql_session;
  1637. Database::query($sql);
  1638. }
  1639. /**
  1640. * get the document id of default certificate
  1641. * @param string $course_id
  1642. * @param int $session_id
  1643. *
  1644. * @return int The default certificate id
  1645. */
  1646. public static function get_default_certificate_id($course_id, $session_id = 0)
  1647. {
  1648. $tbl_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1649. $session_id = intval($session_id);
  1650. if (empty($session_id)) {
  1651. $session_id = api_get_session_id();
  1652. }
  1653. if (empty($session_id)) {
  1654. $sql_session = 'AND (session_id = 0 OR isnull(session_id)) ';
  1655. } elseif ($session_id > 0) {
  1656. $sql_session = 'AND session_id='.intval($session_id);
  1657. } else {
  1658. $sql_session = '';
  1659. }
  1660. $sql = 'SELECT document_id FROM '.$tbl_category.'
  1661. WHERE course_code="' . Database::escape_string($course_id).'" '.$sql_session;
  1662. $rs = Database::query($sql);
  1663. $num = Database::num_rows($rs);
  1664. if ($num == 0) {
  1665. return null;
  1666. }
  1667. $row = Database::fetch_array($rs);
  1668. return $row['document_id'];
  1669. }
  1670. /**
  1671. * Allow replace user info in file html
  1672. * @param int $user_id
  1673. * @param string $course_code
  1674. * @param int $sessionId
  1675. * @param bool $is_preview
  1676. * @return string The html content of the certificate
  1677. */
  1678. public static function replace_user_info_into_html(
  1679. $user_id,
  1680. $course_code,
  1681. $sessionId,
  1682. $is_preview = false
  1683. ) {
  1684. $user_id = intval($user_id);
  1685. $course_info = api_get_course_info($course_code);
  1686. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  1687. $course_id = $course_info['real_id'];
  1688. $document_id = self::get_default_certificate_id(
  1689. $course_code,
  1690. $sessionId
  1691. );
  1692. $my_content_html = null;
  1693. if ($document_id) {
  1694. $sql = "SELECT path FROM $tbl_document
  1695. WHERE c_id = $course_id AND id = $document_id";
  1696. $rs = Database::query($sql);
  1697. $new_content = '';
  1698. $all_user_info = array();
  1699. if (Database::num_rows($rs)) {
  1700. $row = Database::fetch_array($rs);
  1701. $filepath = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$row['path'];
  1702. if (is_file($filepath)) {
  1703. $my_content_html = file_get_contents($filepath);
  1704. }
  1705. $all_user_info = self::get_all_info_to_certificate(
  1706. $user_id,
  1707. $course_code,
  1708. $is_preview
  1709. );
  1710. $info_to_be_replaced_in_content_html = $all_user_info[0];
  1711. $info_to_replace_in_content_html = $all_user_info[1];
  1712. $new_content = str_replace(
  1713. $info_to_be_replaced_in_content_html,
  1714. $info_to_replace_in_content_html,
  1715. $my_content_html
  1716. );
  1717. }
  1718. return [
  1719. 'content' => $new_content,
  1720. 'variables' => $all_user_info
  1721. ];
  1722. }
  1723. return [];
  1724. }
  1725. /**
  1726. * Return all content to replace and all content to be replace
  1727. * @param int $user_id
  1728. * @param int $course_id
  1729. * @param bool $is_preview
  1730. * @return array
  1731. */
  1732. public static function get_all_info_to_certificate($user_id, $course_id, $is_preview = false)
  1733. {
  1734. $info_list = array();
  1735. $user_id = intval($user_id);
  1736. $course_info = api_get_course_info($course_id);
  1737. // Portal infor
  1738. $organization_name = api_get_setting('Institution');
  1739. $portal_name = api_get_setting('siteName');
  1740. // Extra user data information
  1741. $extra_user_info_data = UserManager::get_extra_user_data(
  1742. $user_id,
  1743. false,
  1744. false,
  1745. false,
  1746. true
  1747. );
  1748. // get extra fields
  1749. $extraField = new ExtraField('user');
  1750. $extraFields = $extraField->get_all(['filter = ? AND visible_to_self = ?' => [1, 1]]);
  1751. //Student information
  1752. $user_info = api_get_user_info($user_id);
  1753. $first_name = $user_info['firstname'];
  1754. $last_name = $user_info['lastname'];
  1755. $official_code = $user_info['official_code'];
  1756. // Teacher information
  1757. $info_teacher_id = UserManager::get_user_id_of_course_admin_or_session_admin($course_info);
  1758. $teacher_info = api_get_user_info($info_teacher_id);
  1759. $teacher_first_name = $teacher_info['firstname'];
  1760. $teacher_last_name = $teacher_info['lastname'];
  1761. // info gradebook certificate
  1762. $info_grade_certificate = UserManager::get_info_gradebook_certificate($course_id, $user_id);
  1763. $date_certificate = $info_grade_certificate['created_at'];
  1764. $date_long_certificate = '';
  1765. $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
  1766. if (!empty($date_certificate)) {
  1767. $date_long_certificate = api_convert_and_format_date($date_certificate);
  1768. $date_no_time = api_convert_and_format_date($date_certificate, DATE_FORMAT_LONG_NO_DAY);
  1769. }
  1770. if ($is_preview) {
  1771. $date_long_certificate = api_convert_and_format_date(api_get_utc_datetime());
  1772. $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
  1773. }
  1774. $url = api_get_path(WEB_PATH).'certificates/index.php?id='.$info_grade_certificate['id'];
  1775. $externalStyleFile = api_get_path(SYS_CSS_PATH).'themes/'.api_get_visual_theme().'/certificate.css';
  1776. $externalStyle = '';
  1777. if (is_file($externalStyleFile)) {
  1778. $externalStyle = file_get_contents($externalStyleFile);
  1779. }
  1780. // Replace content
  1781. $info_to_replace_in_content_html = array(
  1782. $first_name,
  1783. $last_name,
  1784. $organization_name,
  1785. $portal_name,
  1786. $teacher_first_name,
  1787. $teacher_last_name,
  1788. $official_code,
  1789. $date_long_certificate,
  1790. $date_no_time,
  1791. $course_id,
  1792. $course_info['name'],
  1793. $info_grade_certificate['grade'],
  1794. $url,
  1795. '<a href="'.$url.'" target="_blank">'.get_lang('CertificateOnlineLink').'</a>',
  1796. '((certificate_barcode))',
  1797. $externalStyle
  1798. );
  1799. $info_to_be_replaced_in_content_html = array(
  1800. '((user_firstname))',
  1801. '((user_lastname))',
  1802. '((gradebook_institution))',
  1803. '((gradebook_sitename))',
  1804. '((teacher_firstname))',
  1805. '((teacher_lastname))',
  1806. '((official_code))',
  1807. '((date_certificate))',
  1808. '((date_certificate_no_time))',
  1809. '((course_code))',
  1810. '((course_title))',
  1811. '((gradebook_grade))',
  1812. '((certificate_link))',
  1813. '((certificate_link_html))',
  1814. '((certificate_barcode))',
  1815. '((external_style))'
  1816. );
  1817. if (!empty($extraFields)) {
  1818. foreach ($extraFields as $extraField) {
  1819. $valueExtra = isset($extra_user_info_data[$extraField['variable']]) ? $extra_user_info_data[$extraField['variable']] : '';
  1820. $info_to_be_replaced_in_content_html[] = '(('.strtolower($extraField['variable']).'))';
  1821. $info_to_replace_in_content_html[] = $valueExtra;
  1822. }
  1823. }
  1824. $info_list[] = $info_to_be_replaced_in_content_html;
  1825. $info_list[] = $info_to_replace_in_content_html;
  1826. return $info_list;
  1827. }
  1828. /**
  1829. * Remove default certificate
  1830. * @param string $course_id The course code
  1831. * @param int $default_certificate_id The document id of the default certificate
  1832. * @return void
  1833. */
  1834. public static function remove_attach_certificate($course_id, $default_certificate_id)
  1835. {
  1836. if (empty($default_certificate_id)) {
  1837. return false;
  1838. }
  1839. $default_certificate = self::get_default_certificate_id($course_id);
  1840. if ((int) $default_certificate == (int) $default_certificate_id) {
  1841. $tbl_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1842. $session_id = api_get_session_id();
  1843. if ($session_id == 0 || is_null($session_id)) {
  1844. $sql_session = 'AND (session_id='.intval($session_id).' OR isnull(session_id)) ';
  1845. } elseif ($session_id > 0) {
  1846. $sql_session = 'AND session_id='.intval($session_id);
  1847. } else {
  1848. $sql_session = '';
  1849. }
  1850. $sql = 'UPDATE '.$tbl_category.' SET document_id = null
  1851. WHERE
  1852. course_code = "' . Database::escape_string($course_id).'" AND
  1853. document_id="' . $default_certificate_id.'" '.$sql_session;
  1854. Database::query($sql);
  1855. }
  1856. }
  1857. /**
  1858. * Create directory certificate
  1859. * @param array $courseInfo
  1860. * @return void
  1861. */
  1862. public static function create_directory_certificate_in_course($courseInfo)
  1863. {
  1864. if (!empty($courseInfo)) {
  1865. $to_group_id = 0;
  1866. $to_user_id = null;
  1867. $course_dir = $courseInfo['path']."/document/";
  1868. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  1869. $base_work_dir = $sys_course_path.$course_dir;
  1870. $base_work_dir_test = $base_work_dir.'certificates';
  1871. $dir_name = '/certificates';
  1872. $post_dir_name = get_lang('CertificatesFiles');
  1873. $visibility_command = 'invisible';
  1874. $id = self::get_document_id_of_directory_certificate();
  1875. if (empty($id)) {
  1876. create_unexisting_directory(
  1877. $courseInfo,
  1878. api_get_user_id(),
  1879. api_get_session_id(),
  1880. $to_group_id,
  1881. $to_user_id,
  1882. $base_work_dir,
  1883. $dir_name,
  1884. $post_dir_name,
  1885. null,
  1886. false
  1887. );
  1888. $id = self::get_document_id_of_directory_certificate();
  1889. if (empty($id)) {
  1890. $id = add_document(
  1891. $courseInfo,
  1892. $dir_name,
  1893. 'folder',
  1894. 0,
  1895. $post_dir_name,
  1896. null,
  1897. 0,
  1898. true,
  1899. $to_group_id
  1900. );
  1901. }
  1902. if (!empty($id)) {
  1903. api_item_property_update(
  1904. $courseInfo,
  1905. TOOL_DOCUMENT,
  1906. $id,
  1907. $visibility_command,
  1908. api_get_user_id()
  1909. );
  1910. }
  1911. }
  1912. }
  1913. }
  1914. /**
  1915. * Get the document id of the directory certificate
  1916. * @return int The document id of the directory certificate
  1917. */
  1918. public static function get_document_id_of_directory_certificate()
  1919. {
  1920. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  1921. $course_id = api_get_course_int_id();
  1922. $sql = "SELECT id FROM $tbl_document
  1923. WHERE c_id = $course_id AND path='/certificates' ";
  1924. $rs = Database::query($sql);
  1925. $row = Database::fetch_array($rs);
  1926. return $row['id'];
  1927. }
  1928. /**
  1929. * Check if a directory given is for certificate
  1930. * @param string $dir path of directory
  1931. * @return bool true if is a certificate or false otherwise
  1932. */
  1933. public static function is_certificate_mode($dir)
  1934. {
  1935. // I'm in the certification module?
  1936. $is_certificate_mode = false;
  1937. $is_certificate_array = explode('/', $dir);
  1938. array_shift($is_certificate_array);
  1939. if (isset($is_certificate_array[0]) && $is_certificate_array[0] == 'certificates') {
  1940. $is_certificate_mode = true;
  1941. }
  1942. return $is_certificate_mode;
  1943. }
  1944. /**
  1945. * Gets the list of included resources as a list of absolute or relative paths from a html file or string html
  1946. * This allows for a better SCORM export or replace urls inside content html from copy course
  1947. * The list will generally include pictures, flash objects, java applets, or any other
  1948. * stuff included in the source of the current item. The current item is expected
  1949. * to be an HTML file or string html. If it is not, then the function will return and empty list.
  1950. * @param string source html (content or path)
  1951. * @param bool is file or string html
  1952. * @param string type (one of the app tools) - optional (otherwise takes the current item's type)
  1953. * @param int level of recursivity we're in
  1954. * @return array List of file paths. An additional field containing 'local' or 'remote' helps determine
  1955. * if the file should be copied into the zip or just linked
  1956. */
  1957. public static function get_resources_from_source_html($source_html, $is_file = false, $type = null, $recursivity = 1)
  1958. {
  1959. $max = 5;
  1960. $attributes = array();
  1961. $wanted_attributes = array('src', 'url', '@import', 'href', 'value', 'flashvars', 'poster');
  1962. $explode_attributes = array('flashvars' => 'file');
  1963. $abs_path = '';
  1964. if ($recursivity > $max) {
  1965. return array();
  1966. }
  1967. if (!isset($type)) {
  1968. $type = TOOL_DOCUMENT;
  1969. }
  1970. if (!$is_file) {
  1971. $attributes = self::parse_HTML_attributes($source_html, $wanted_attributes, $explode_attributes);
  1972. } else {
  1973. if (is_file($source_html)) {
  1974. $abs_path = $source_html;
  1975. //for now, read the whole file in one go (that's gonna be a problem when the file is too big)
  1976. $info = pathinfo($abs_path);
  1977. $ext = $info['extension'];
  1978. switch (strtolower($ext)) {
  1979. case 'html':
  1980. case 'htm':
  1981. case 'shtml':
  1982. case 'css':
  1983. $file_content = file_get_contents($abs_path);
  1984. //get an array of attributes from the HTML source
  1985. $attributes = self::parse_HTML_attributes($file_content, $wanted_attributes, $explode_attributes);
  1986. break;
  1987. default:
  1988. break;
  1989. }
  1990. } else {
  1991. return false;
  1992. }
  1993. }
  1994. $files_list = array();
  1995. switch ($type) {
  1996. case TOOL_DOCUMENT:
  1997. case TOOL_QUIZ:
  1998. case 'sco':
  1999. foreach ($wanted_attributes as $attr) {
  2000. if (isset($attributes[$attr])) {
  2001. //find which kind of path these are (local or remote)
  2002. $sources = $attributes[$attr];
  2003. foreach ($sources as $source) {
  2004. //skip what is obviously not a resource
  2005. if (strpos($source, '+this.')) {
  2006. continue; //javascript code - will still work unaltered
  2007. }
  2008. if (strpos($source, '.') === false) {
  2009. continue; //no dot, should not be an external file anyway
  2010. }
  2011. if (strpos($source, 'mailto:')) {
  2012. continue; //mailto link
  2013. }
  2014. if (strpos($source, ';') && !strpos($source, '&amp;')) {
  2015. continue; //avoid code - that should help
  2016. }
  2017. if ($attr == 'value') {
  2018. if (strpos($source, 'mp3file')) {
  2019. $files_list[] = array(substr($source, 0, strpos($source, '.swf') + 4), 'local', 'abs');
  2020. $mp3file = substr($source, strpos($source, 'mp3file=') + 8);
  2021. if (substr($mp3file, 0, 1) == '/') {
  2022. $files_list[] = array($mp3file, 'local', 'abs');
  2023. } else {
  2024. $files_list[] = array($mp3file, 'local', 'rel');
  2025. }
  2026. } elseif (strpos($source, 'flv=') === 0) {
  2027. $source = substr($source, 4);
  2028. if (strpos($source, '&') > 0) {
  2029. $source = substr($source, 0, strpos($source, '&'));
  2030. }
  2031. if (strpos($source, '://') > 0) {
  2032. if (strpos($source, api_get_path(WEB_PATH)) !== false) {
  2033. //we found the current portal url
  2034. $files_list[] = array($source, 'local', 'url');
  2035. } else {
  2036. //we didn't find any trace of current portal
  2037. $files_list[] = array($source, 'remote', 'url');
  2038. }
  2039. } else {
  2040. $files_list[] = array($source, 'local', 'abs');
  2041. }
  2042. /* skipping anything else to avoid two entries
  2043. (while the others can have sub-files in their url, flv's can't)*/
  2044. continue;
  2045. }
  2046. }
  2047. if (strpos($source, '://') > 0) {
  2048. //cut at '?' in a URL with params
  2049. if (strpos($source, '?') > 0) {
  2050. $second_part = substr($source, strpos($source, '?'));
  2051. if (strpos($second_part, '://') > 0) {
  2052. //if the second part of the url contains a url too, treat the second one before cutting
  2053. $pos1 = strpos($second_part, '=');
  2054. $pos2 = strpos($second_part, '&');
  2055. $second_part = substr($second_part, $pos1 + 1, $pos2 - ($pos1 + 1));
  2056. if (strpos($second_part, api_get_path(WEB_PATH)) !== false) {
  2057. //we found the current portal url
  2058. $files_list[] = array($second_part, 'local', 'url');
  2059. $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
  2060. if (count($in_files_list) > 0) {
  2061. $files_list = array_merge($files_list, $in_files_list);
  2062. }
  2063. } else {
  2064. //we didn't find any trace of current portal
  2065. $files_list[] = array($second_part, 'remote', 'url');
  2066. }
  2067. } elseif (strpos($second_part, '=') > 0) {
  2068. if (substr($second_part, 0, 1) === '/') {
  2069. //link starts with a /, making it absolute (relative to DocumentRoot)
  2070. $files_list[] = array($second_part, 'local', 'abs');
  2071. $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
  2072. if (count($in_files_list) > 0) {
  2073. $files_list = array_merge($files_list, $in_files_list);
  2074. }
  2075. } elseif (strstr($second_part, '..') === 0) {
  2076. //link is relative but going back in the hierarchy
  2077. $files_list[] = array($second_part, 'local', 'rel');
  2078. //$dir = api_get_path(SYS_CODE_PATH);//dirname($abs_path);
  2079. //$new_abs_path = realpath($dir.'/'.$second_part);
  2080. $dir = '';
  2081. if (!empty($abs_path)) {
  2082. $dir = dirname($abs_path).'/';
  2083. }
  2084. $new_abs_path = realpath($dir.$second_part);
  2085. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2086. if (count($in_files_list) > 0) {
  2087. $files_list = array_merge($files_list, $in_files_list);
  2088. }
  2089. } else {
  2090. //no starting '/', making it relative to current document's path
  2091. if (substr($second_part, 0, 2) == './') {
  2092. $second_part = substr($second_part, 2);
  2093. }
  2094. $files_list[] = array($second_part, 'local', 'rel');
  2095. $dir = '';
  2096. if (!empty($abs_path)) {
  2097. $dir = dirname($abs_path).'/';
  2098. }
  2099. $new_abs_path = realpath($dir.$second_part);
  2100. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2101. if (count($in_files_list) > 0) {
  2102. $files_list = array_merge($files_list, $in_files_list);
  2103. }
  2104. }
  2105. }
  2106. //leave that second part behind now
  2107. $source = substr($source, 0, strpos($source, '?'));
  2108. if (strpos($source, '://') > 0) {
  2109. if (strpos($source, api_get_path(WEB_PATH)) !== false) {
  2110. //we found the current portal url
  2111. $files_list[] = array($source, 'local', 'url');
  2112. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  2113. if (count($in_files_list) > 0) {
  2114. $files_list = array_merge($files_list, $in_files_list);
  2115. }
  2116. } else {
  2117. //we didn't find any trace of current portal
  2118. $files_list[] = array($source, 'remote', 'url');
  2119. }
  2120. } else {
  2121. //no protocol found, make link local
  2122. if (substr($source, 0, 1) === '/') {
  2123. //link starts with a /, making it absolute (relative to DocumentRoot)
  2124. $files_list[] = array($source, 'local', 'abs');
  2125. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  2126. if (count($in_files_list) > 0) {
  2127. $files_list = array_merge($files_list, $in_files_list);
  2128. }
  2129. } elseif (strstr($source, '..') === 0) { //link is relative but going back in the hierarchy
  2130. $files_list[] = array($source, 'local', 'rel');
  2131. $dir = '';
  2132. if (!empty($abs_path)) {
  2133. $dir = dirname($abs_path).'/';
  2134. }
  2135. $new_abs_path = realpath($dir.$source);
  2136. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2137. if (count($in_files_list) > 0) {
  2138. $files_list = array_merge($files_list, $in_files_list);
  2139. }
  2140. } else {
  2141. //no starting '/', making it relative to current document's path
  2142. if (substr($source, 0, 2) == './') {
  2143. $source = substr($source, 2);
  2144. }
  2145. $files_list[] = array($source, 'local', 'rel');
  2146. $dir = '';
  2147. if (!empty($abs_path)) {
  2148. $dir = dirname($abs_path).'/';
  2149. }
  2150. $new_abs_path = realpath($dir.$source);
  2151. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2152. if (count($in_files_list) > 0) {
  2153. $files_list = array_merge($files_list, $in_files_list);
  2154. }
  2155. }
  2156. }
  2157. }
  2158. //found some protocol there
  2159. if (strpos($source, api_get_path(WEB_PATH)) !== false) {
  2160. //we found the current portal url
  2161. $files_list[] = array($source, 'local', 'url');
  2162. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  2163. if (count($in_files_list) > 0) {
  2164. $files_list = array_merge($files_list, $in_files_list);
  2165. }
  2166. } else {
  2167. //we didn't find any trace of current portal
  2168. $files_list[] = array($source, 'remote', 'url');
  2169. }
  2170. } else {
  2171. //no protocol found, make link local
  2172. if (substr($source, 0, 1) === '/') {
  2173. //link starts with a /, making it absolute (relative to DocumentRoot)
  2174. $files_list[] = array($source, 'local', 'abs');
  2175. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  2176. if (count($in_files_list) > 0) {
  2177. $files_list = array_merge($files_list, $in_files_list);
  2178. }
  2179. } elseif (strpos($source, '..') === 0) {
  2180. //link is relative but going back in the hierarchy
  2181. $files_list[] = array($source, 'local', 'rel');
  2182. $dir = '';
  2183. if (!empty($abs_path)) {
  2184. $dir = dirname($abs_path).'/';
  2185. }
  2186. $new_abs_path = realpath($dir.$source);
  2187. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2188. if (count($in_files_list) > 0) {
  2189. $files_list = array_merge($files_list, $in_files_list);
  2190. }
  2191. } else {
  2192. //no starting '/', making it relative to current document's path
  2193. if (substr($source, 0, 2) == './') {
  2194. $source = substr($source, 2);
  2195. }
  2196. $files_list[] = array($source, 'local', 'rel');
  2197. $dir = '';
  2198. if (!empty($abs_path)) {
  2199. $dir = dirname($abs_path).'/';
  2200. }
  2201. $new_abs_path = realpath($dir.$source);
  2202. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2203. if (count($in_files_list) > 0) {
  2204. $files_list = array_merge($files_list, $in_files_list);
  2205. }
  2206. }
  2207. }
  2208. }
  2209. }
  2210. }
  2211. break;
  2212. default: //ignore
  2213. break;
  2214. }
  2215. $checked_files_list = array();
  2216. $checked_array_list = array();
  2217. if (count($files_list) > 0) {
  2218. foreach ($files_list as $idx => $file) {
  2219. if (!empty($file[0])) {
  2220. if (!in_array($file[0], $checked_files_list)) {
  2221. $checked_files_list[] = $files_list[$idx][0];
  2222. $checked_array_list[] = $files_list[$idx];
  2223. }
  2224. }
  2225. }
  2226. }
  2227. return $checked_array_list;
  2228. }
  2229. /**
  2230. * Parses the HTML attributes given as string.
  2231. *
  2232. * @param string HTML attribute string
  2233. * @param array List of attributes that we want to get back
  2234. * @param array
  2235. * @return array An associative array of attributes
  2236. * @author Based on a function from the HTML_Common2 PEAR module *
  2237. */
  2238. public static function parse_HTML_attributes($attrString, $wanted = array(), $explode_variables = array())
  2239. {
  2240. $attributes = array();
  2241. $regs = array();
  2242. $reduced = false;
  2243. if (count($wanted) > 0) {
  2244. $reduced = true;
  2245. }
  2246. try {
  2247. //Find all occurences of something that looks like a URL
  2248. // The structure of this regexp is:
  2249. // (find protocol) then
  2250. // (optionally find some kind of space 1 or more times) then
  2251. // find (either an equal sign or a bracket) followed by an optional space
  2252. // followed by some text without quotes (between quotes itself or not)
  2253. // then possible closing brackets if we were in the opening bracket case
  2254. // OR something like @import()
  2255. $res = preg_match_all(
  2256. '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]*))'.
  2257. // '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]|[^\x00-\x7F])*)' . -> seems to be taking too much
  2258. // '/(((([A-Za-z_:])([^\x00-\x7F])*)' . -> takes only last letter of parameter name
  2259. '([ \n\t\r]+)?('.
  2260. // '(=([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+))' . -> doesn't restrict close enough to the url itself
  2261. '(=([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+))'.
  2262. '|'.
  2263. // '(\(([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)\))' . -> doesn't restrict close enough to the url itself
  2264. '(\(([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+)\))'.
  2265. '))'.
  2266. '|'.
  2267. // '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))?/', -> takes a lot (like 100's of thousands of empty possibilities)
  2268. '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))/',
  2269. $attrString,
  2270. $regs
  2271. );
  2272. } catch (Exception $e) {
  2273. error_log('Caught exception: '.$e->getMessage(), 0);
  2274. }
  2275. if ($res) {
  2276. for ($i = 0; $i < count($regs[1]); $i++) {
  2277. $name = trim($regs[3][$i]);
  2278. $check = trim($regs[0][$i]);
  2279. $value = trim($regs[10][$i]);
  2280. if (empty($value) and !empty($regs[13][$i])) {
  2281. $value = $regs[13][$i];
  2282. }
  2283. if (empty($name) && !empty($regs[16][$i])) {
  2284. $name = '@import';
  2285. $value = trim($regs[16][$i]);
  2286. }
  2287. if (!empty($name)) {
  2288. if (!$reduced OR in_array(strtolower($name), $wanted)) {
  2289. if ($name == $check) {
  2290. $attributes[strtolower($name)][] = strtolower($name);
  2291. } else {
  2292. if (!empty($value) && ($value[0] == '\'' || $value[0] == '"')) {
  2293. $value = substr($value, 1, -1);
  2294. }
  2295. if ($value == 'API.LMSGetValue(name') {
  2296. $value = 'API.LMSGetValue(name)';
  2297. }
  2298. //Gets the xx.flv value from the string flashvars="width=320&height=240&autostart=false&file=xxx.flv&repeat=false"
  2299. if (isset($explode_variables[$name])) {
  2300. $value_modified = str_replace('&amp;', '&', $value);
  2301. $value_array = explode('&', $value_modified);
  2302. foreach ($value_array as $item) {
  2303. list($key, $item_value) = explode('=', $item);
  2304. if ($key == $explode_variables[$name]) {
  2305. $attributes[strtolower($name)][] = $item_value;
  2306. }
  2307. }
  2308. }
  2309. $attributes[strtolower($name)][] = $value;
  2310. }
  2311. }
  2312. }
  2313. }
  2314. }
  2315. return $attributes;
  2316. }
  2317. /**
  2318. * Replace urls inside content html from a copy course
  2319. * @param string $content_html
  2320. * @param string $origin_course_code
  2321. * @param string $destination_course_directory
  2322. * @param string $origin_course_path_from_zip
  2323. * @param string $origin_course_info_path
  2324. *
  2325. * @return string new content html with replaced urls or return false if content is not a string
  2326. */
  2327. public static function replace_urls_inside_content_html_from_copy_course(
  2328. $content_html,
  2329. $origin_course_code,
  2330. $destination_course_directory,
  2331. $origin_course_path_from_zip = null,
  2332. $origin_course_info_path = null
  2333. ) {
  2334. if (empty($content_html)) {
  2335. return false;
  2336. }
  2337. $orig_source_html = self::get_resources_from_source_html($content_html);
  2338. $orig_course_info = api_get_course_info($origin_course_code);
  2339. // Course does not exist in the current DB probably this came from a zip file?
  2340. if (empty($orig_course_info)) {
  2341. if (!empty($origin_course_path_from_zip)) {
  2342. $orig_course_path = $origin_course_path_from_zip.'/';
  2343. $orig_course_info_path = $origin_course_info_path;
  2344. }
  2345. } else {
  2346. $orig_course_path = api_get_path(SYS_COURSE_PATH).$orig_course_info['path'].'/';
  2347. $orig_course_info_path = $orig_course_info['path'];
  2348. }
  2349. $destination_course_code = CourseManager::get_course_id_from_path($destination_course_directory);
  2350. $destination_course_info = api_get_course_info($destination_course_code);
  2351. $dest_course_path = api_get_path(SYS_COURSE_PATH).$destination_course_directory.'/';
  2352. $dest_course_path_rel = api_get_path(REL_COURSE_PATH).$destination_course_directory.'/';
  2353. $user_id = api_get_user_id();
  2354. if (!empty($orig_source_html)) {
  2355. foreach ($orig_source_html as $source) {
  2356. // Get information about source url
  2357. $real_orig_url = $source[0]; // url
  2358. $scope_url = $source[1]; // scope (local, remote)
  2359. $type_url = $source[2]; // type (rel, abs, url)
  2360. // Get path and query from origin url
  2361. $orig_parse_url = parse_url($real_orig_url);
  2362. $real_orig_path = isset($orig_parse_url['path']) ? $orig_parse_url['path'] : null;
  2363. $real_orig_query = isset($orig_parse_url['query']) ? $orig_parse_url['query'] : null;
  2364. // Replace origin course code by destination course code from origin url query
  2365. $dest_url_query = '';
  2366. if (!empty($real_orig_query)) {
  2367. $dest_url_query = '?'.$real_orig_query;
  2368. if (strpos($dest_url_query, $origin_course_code) !== false) {
  2369. $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
  2370. }
  2371. }
  2372. if ($scope_url == 'local') {
  2373. if ($type_url == 'abs' || $type_url == 'rel') {
  2374. $document_file = strstr($real_orig_path, 'document');
  2375. if (strpos($real_orig_path, $document_file) !== false) {
  2376. $origin_filepath = $orig_course_path.$document_file;
  2377. $destination_filepath = $dest_course_path.$document_file;
  2378. // copy origin file inside destination course
  2379. if (file_exists($origin_filepath)) {
  2380. $filepath_dir = dirname($destination_filepath);
  2381. if (!is_dir($filepath_dir)) {
  2382. $perm = api_get_permissions_for_new_directories();
  2383. $result = @mkdir($filepath_dir, $perm, true);
  2384. if ($result) {
  2385. $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $filepath_dir);
  2386. //Add to item properties to the new folder
  2387. $doc_id = add_document(
  2388. $destination_course_info,
  2389. $filepath_to_add,
  2390. 'folder',
  2391. 0,
  2392. basename($filepath_to_add)
  2393. );
  2394. api_item_property_update(
  2395. $destination_course_info,
  2396. TOOL_DOCUMENT,
  2397. $doc_id,
  2398. 'FolderCreated',
  2399. $user_id,
  2400. null,
  2401. null,
  2402. null,
  2403. null
  2404. );
  2405. }
  2406. }
  2407. if (!file_exists($destination_filepath)) {
  2408. $result = @copy($origin_filepath, $destination_filepath);
  2409. if ($result) {
  2410. $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $destination_filepath);
  2411. $size = filesize($destination_filepath);
  2412. // Add to item properties to the file
  2413. $doc_id = add_document(
  2414. $destination_course_info,
  2415. $filepath_to_add,
  2416. 'file',
  2417. $size,
  2418. basename($filepath_to_add)
  2419. );
  2420. api_item_property_update(
  2421. $destination_course_info,
  2422. TOOL_DOCUMENT,
  2423. $doc_id,
  2424. 'FolderCreated',
  2425. $user_id,
  2426. null,
  2427. null,
  2428. null,
  2429. null
  2430. );
  2431. }
  2432. }
  2433. }
  2434. // Replace origin course path by destination course path.
  2435. if (strpos($content_html, $real_orig_url) !== false) {
  2436. $url_course_path = str_replace($orig_course_info_path.'/'.$document_file, '', $real_orig_path);
  2437. //$destination_url = $url_course_path . $destination_course_directory . '/' . $document_file . $dest_url_query;
  2438. // See BT#7780
  2439. $destination_url = $dest_course_path_rel.$document_file.$dest_url_query;
  2440. // If the course code doesn't exist in the path? what we do? Nothing! see BT#1985
  2441. if (strpos($real_orig_path, $origin_course_code) === false) {
  2442. $url_course_path = $real_orig_path;
  2443. $destination_url = $real_orig_path;
  2444. }
  2445. $content_html = str_replace($real_orig_url, $destination_url, $content_html);
  2446. }
  2447. }
  2448. // replace origin course code by destination course code from origin url
  2449. if (strpos($real_orig_url, '?') === 0) {
  2450. $dest_url = str_replace($origin_course_code, $destination_course_code, $real_orig_url);
  2451. $content_html = str_replace($real_orig_url, $dest_url, $content_html);
  2452. }
  2453. }
  2454. }
  2455. }
  2456. }
  2457. return $content_html;
  2458. }
  2459. /**
  2460. * Replace urls inside content html when moving a file
  2461. * @todo this code is only called in document.php but is commented
  2462. * @param string content html
  2463. * @param string origin
  2464. * @param string destination
  2465. * @return string new content html with replaced urls or return false if content is not a string
  2466. */
  2467. public function replace_urls_inside_content_html_when_moving_file($file_name, $original_path, $destiny_path)
  2468. {
  2469. if (substr($original_path, strlen($original_path) - 1, strlen($original_path)) == '/') {
  2470. $original = $original_path.$file_name;
  2471. } else {
  2472. $original = $original_path.'/'.$file_name;
  2473. }
  2474. if (substr($destiny_path, strlen($destiny_path) - 1, strlen($destiny_path)) == '/') {
  2475. $destination = $destiny_path.$file_name;
  2476. } else {
  2477. $destination = $destiny_path.'/'.$file_name;
  2478. }
  2479. $original_count = count(explode('/', $original));
  2480. $destination_count = count(explode('/', $destination));
  2481. if ($original_count == $destination_count) {
  2482. //Nothing to change
  2483. return true;
  2484. }
  2485. if ($original_count > $destination_count) {
  2486. $mode = 'outside';
  2487. } else {
  2488. $mode = 'inside';
  2489. }
  2490. //We do not select the $original_path becayse the file was already moved
  2491. $content_html = file_get_contents($destiny_path.'/'.$file_name);
  2492. $destination_file = $destiny_path.'/'.$file_name;
  2493. $pre_original = strstr($original_path, 'document');
  2494. $pre_destin = strstr($destiny_path, 'document');
  2495. $pre_original = substr($pre_original, 8, strlen($pre_original));
  2496. $pre_destin = substr($pre_destin, 8, strlen($pre_destin));
  2497. $levels = count(explode('/', $pre_destin)) - 1;
  2498. $link_to_add = '';
  2499. for ($i = 1; $i <= $levels; $i++) {
  2500. $link_to_add .= '../';
  2501. }
  2502. if ($pre_original == '/') {
  2503. $pre_original = '';
  2504. }
  2505. if ($pre_destin == '/') {
  2506. $pre_destin = '';
  2507. }
  2508. if ($pre_original != '') {
  2509. $pre_original = '..'.$pre_original.'/';
  2510. }
  2511. if ($pre_destin != '') {
  2512. $pre_destin = '..'.$pre_destin.'/';
  2513. }
  2514. $levels = explode('/', $pre_original);
  2515. $count_pre_destination_levels = 0;
  2516. foreach ($levels as $item) {
  2517. if (!empty($item) && $item != '..') {
  2518. $count_pre_destination_levels++;
  2519. }
  2520. }
  2521. $count_pre_destination_levels--;
  2522. //$count_pre_destination_levels = count() - 3;
  2523. if ($count_pre_destination_levels == 0) {
  2524. $count_pre_destination_levels = 1;
  2525. }
  2526. //echo '$count_pre_destination_levels '. $count_pre_destination_levels;
  2527. $pre_remove = '';
  2528. for ($i = 1; $i <= $count_pre_destination_levels; $i++) {
  2529. $pre_remove .= '..\/';
  2530. }
  2531. $orig_source_html = self::get_resources_from_source_html($content_html);
  2532. foreach ($orig_source_html as $source) {
  2533. // get information about source url
  2534. $real_orig_url = $source[0]; // url
  2535. $scope_url = $source[1]; // scope (local, remote)
  2536. $type_url = $source[2]; // tyle (rel, abs, url)
  2537. // Get path and query from origin url
  2538. $orig_parse_url = parse_url($real_orig_url);
  2539. $real_orig_path = $orig_parse_url['path'];
  2540. $real_orig_query = $orig_parse_url['query'];
  2541. // Replace origin course code by destination course code from origin url query
  2542. /*
  2543. $dest_url_query = '';
  2544. if (!empty($real_orig_query)) {
  2545. $dest_url_query = '?'.$real_orig_query;
  2546. if (strpos($dest_url_query,$origin_course_code) !== false) {
  2547. $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
  2548. }
  2549. } */
  2550. if ($scope_url == 'local') {
  2551. if ($type_url == 'abs' || $type_url == 'rel') {
  2552. $document_file = strstr($real_orig_path, 'document');
  2553. if (strpos($real_orig_path, $document_file) !== false) {
  2554. echo 'continue1';
  2555. continue;
  2556. } else {
  2557. $real_orig_url_temp = '';
  2558. if ($mode == 'inside') {
  2559. $real_orig_url_temp = str_replace('../', '', $real_orig_url);
  2560. $destination_url = $link_to_add.$real_orig_url_temp;
  2561. } else {
  2562. $real_orig_url_temp = $real_orig_url;
  2563. $destination_url = preg_replace("/".$pre_remove."/", '', $real_orig_url, 1);
  2564. }
  2565. if ($real_orig_url == $destination_url) {
  2566. //echo 'continue2';
  2567. continue;
  2568. }
  2569. $content_html = str_replace($real_orig_url, $destination_url, $content_html);
  2570. }
  2571. } else {
  2572. echo 'continue3';
  2573. continue;
  2574. }
  2575. }
  2576. }
  2577. $return = file_put_contents($destination, $content_html);
  2578. return $return;
  2579. }
  2580. /**
  2581. * Export document to PDF
  2582. *
  2583. * @param int $document_id
  2584. * @param string $courseCode
  2585. * @param string $orientation
  2586. * @param bool $showHeaderAndFooter
  2587. */
  2588. public static function export_to_pdf(
  2589. $document_id,
  2590. $courseCode,
  2591. $orientation = 'landscape',
  2592. $showHeaderAndFooter = true
  2593. ) {
  2594. $course_data = api_get_course_info($courseCode);
  2595. $document_data = self::get_document_data_by_id($document_id, $courseCode);
  2596. $file_path = api_get_path(SYS_COURSE_PATH).$course_data['path'].'/document'.$document_data['path'];
  2597. if ($orientation == 'landscape') {
  2598. $pageFormat = 'A4-L';
  2599. $pdfOrientation = 'L';
  2600. } else {
  2601. $pageFormat = 'A4';
  2602. $pdfOrientation = 'P';
  2603. }
  2604. $pdf = new PDF($pageFormat, $pdfOrientation);
  2605. $pdf->html_to_pdf(
  2606. $file_path,
  2607. $document_data['title'],
  2608. $courseCode,
  2609. false,
  2610. $showHeaderAndFooter
  2611. );
  2612. }
  2613. /**
  2614. * Uploads a document
  2615. *
  2616. * @param array $files the $_FILES variable
  2617. * @param string $path
  2618. * @param string $title
  2619. * @param string $comment
  2620. * @param int $unzip unzip or not the file
  2621. * @param string $if_exists overwrite, rename or warn (default)
  2622. * @param bool $index_document index document (search xapian module)
  2623. * @param bool $show_output print html messages
  2624. * @param string $fileKey
  2625. * @param bool $treat_spaces_as_hyphens
  2626. *
  2627. * @return array|bool
  2628. */
  2629. public static function upload_document(
  2630. $files,
  2631. $path,
  2632. $title = null,
  2633. $comment = null,
  2634. $unzip = 0,
  2635. $if_exists = null,
  2636. $index_document = false,
  2637. $show_output = false,
  2638. $fileKey = 'file',
  2639. $treat_spaces_as_hyphens = true
  2640. ) {
  2641. $course_info = api_get_course_info();
  2642. $sessionId = api_get_session_id();
  2643. $course_dir = $course_info['path'].'/document';
  2644. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  2645. $base_work_dir = $sys_course_path.$course_dir;
  2646. $group_properties = GroupManager::get_group_properties(api_get_group_id());
  2647. $groupIid = isset($group_properties['iid']) ? $group_properties['iid'] : 0;
  2648. if (isset($files[$fileKey])) {
  2649. $upload_ok = process_uploaded_file($files[$fileKey], $show_output);
  2650. if ($upload_ok) {
  2651. $new_path = handle_uploaded_document(
  2652. $course_info,
  2653. $files[$fileKey],
  2654. $base_work_dir,
  2655. $path,
  2656. api_get_user_id(),
  2657. $groupIid,
  2658. null,
  2659. $unzip,
  2660. $if_exists,
  2661. $show_output,
  2662. false,
  2663. null,
  2664. $sessionId,
  2665. $treat_spaces_as_hyphens
  2666. );
  2667. // Showing message when sending zip files
  2668. if ($new_path === true && $unzip == 1) {
  2669. if ($show_output) {
  2670. Display::display_confirmation_message(
  2671. get_lang('UplUploadSucceeded').'<br />',
  2672. false
  2673. );
  2674. }
  2675. return [
  2676. 'title' => $path,
  2677. 'url' => $path,
  2678. ];
  2679. }
  2680. if ($new_path) {
  2681. $documentId = self::get_document_id(
  2682. $course_info,
  2683. $new_path,
  2684. $sessionId
  2685. );
  2686. if (!empty($documentId)) {
  2687. $table_document = Database::get_course_table(TABLE_DOCUMENT);
  2688. $params = array();
  2689. /*if ($if_exists == 'rename') {
  2690. // Remove prefix
  2691. $suffix = self::getDocumentSuffix(
  2692. $course_info,
  2693. $sessionId,
  2694. api_get_group_id()
  2695. );
  2696. $new_path = basename($new_path);
  2697. $new_path = str_replace($suffix, '', $new_path);
  2698. error_log('renamed');
  2699. error_log($new_path);
  2700. $params['title'] = get_document_title($new_path);
  2701. } else {
  2702. if (!empty($title)) {
  2703. $params['title'] = get_document_title($title);
  2704. } else {
  2705. $params['title'] = get_document_title($files['file']['name']);
  2706. }
  2707. }*/
  2708. if (!empty($title)) {
  2709. $params['title'] = $title;
  2710. }
  2711. if (!empty($comment)) {
  2712. $params['comment'] = trim($comment);
  2713. }
  2714. Database::update(
  2715. $table_document,
  2716. $params,
  2717. array(
  2718. 'id = ? AND c_id = ? ' => array(
  2719. $documentId,
  2720. $course_info['real_id']
  2721. )
  2722. )
  2723. );
  2724. }
  2725. if ($index_document) {
  2726. self::index_document(
  2727. $documentId,
  2728. $course_info['code'],
  2729. null,
  2730. $_POST['language'],
  2731. $_REQUEST,
  2732. $if_exists
  2733. );
  2734. }
  2735. if (!empty($documentId) && is_numeric($documentId)) {
  2736. $documentData = self::get_document_data_by_id(
  2737. $documentId,
  2738. $course_info['code'],
  2739. false,
  2740. $sessionId
  2741. );
  2742. return $documentData;
  2743. }
  2744. }
  2745. }
  2746. }
  2747. return false;
  2748. }
  2749. /**
  2750. * Obtains the text inside the file with the right parser
  2751. */
  2752. public static function get_text_content($doc_path, $doc_mime)
  2753. {
  2754. // TODO: review w$ compatibility
  2755. // Use usual exec output lines array to store stdout instead of a temp file
  2756. // because we need to store it at RAM anyway before index on ChamiloIndexer object
  2757. $ret_val = null;
  2758. switch ($doc_mime) {
  2759. case 'text/plain':
  2760. $handle = fopen($doc_path, 'r');
  2761. $output = array(fread($handle, filesize($doc_path)));
  2762. fclose($handle);
  2763. break;
  2764. case 'application/pdf':
  2765. exec("pdftotext $doc_path -", $output, $ret_val);
  2766. break;
  2767. case 'application/postscript':
  2768. $temp_file = tempnam(sys_get_temp_dir(), 'chamilo');
  2769. exec("ps2pdf $doc_path $temp_file", $output, $ret_val);
  2770. if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
  2771. return false;
  2772. }
  2773. exec("pdftotext $temp_file -", $output, $ret_val);
  2774. unlink($temp_file);
  2775. break;
  2776. case 'application/msword':
  2777. exec("catdoc $doc_path", $output, $ret_val);
  2778. break;
  2779. case 'text/html':
  2780. exec("html2text $doc_path", $output, $ret_val);
  2781. break;
  2782. case 'text/rtf':
  2783. // Note: correct handling of code pages in unrtf
  2784. // on debian lenny unrtf v0.19.2 can not, but unrtf v0.20.5 can
  2785. exec("unrtf --text $doc_path", $output, $ret_val);
  2786. if ($ret_val == 127) { // command not found
  2787. return false;
  2788. }
  2789. // Avoid index unrtf comments
  2790. if (is_array($output) && count($output) > 1) {
  2791. $parsed_output = array();
  2792. foreach ($output as & $line) {
  2793. if (!preg_match('/^###/', $line, $matches)) {
  2794. if (!empty($line)) {
  2795. $parsed_output[] = $line;
  2796. }
  2797. }
  2798. }
  2799. $output = $parsed_output;
  2800. }
  2801. break;
  2802. case 'application/vnd.ms-powerpoint':
  2803. exec("catppt $doc_path", $output, $ret_val);
  2804. break;
  2805. case 'application/vnd.ms-excel':
  2806. exec("xls2csv -c\" \" $doc_path", $output, $ret_val);
  2807. break;
  2808. }
  2809. $content = '';
  2810. if (!is_null($ret_val)) {
  2811. if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
  2812. return false;
  2813. }
  2814. }
  2815. if (isset($output)) {
  2816. foreach ($output as & $line) {
  2817. $content .= $line."\n";
  2818. }
  2819. return $content;
  2820. } else {
  2821. return false;
  2822. }
  2823. }
  2824. /**
  2825. * Calculates the total size of all documents in a course
  2826. *
  2827. * @author Bert vanderkimpen
  2828. * @param int $course_id
  2829. * @param int $group_id (to calculate group document space)
  2830. * @param int $session_id
  2831. *
  2832. * @return int total size
  2833. */
  2834. public static function documents_total_space($course_id = null, $group_id = null, $session_id = null)
  2835. {
  2836. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  2837. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  2838. if (isset($course_id)) {
  2839. $course_id = intval($course_id);
  2840. } else {
  2841. $course_id = api_get_course_int_id();
  2842. }
  2843. $group_condition = null;
  2844. if (isset($group_id)) {
  2845. $group_id = intval($group_id);
  2846. $group_condition = " AND props.to_group_id='".$group_id."' ";
  2847. }
  2848. $session_condition = null;
  2849. if (isset($session_id)) {
  2850. $session_id = intval($session_id);
  2851. $session_condition = " AND props.session_id='".$session_id."' ";
  2852. }
  2853. $sql = "SELECT SUM(size)
  2854. FROM $TABLE_ITEMPROPERTY AS props
  2855. INNER JOIN $TABLE_DOCUMENT AS docs
  2856. ON (docs.id = props.ref AND props.c_id = docs.c_id)
  2857. WHERE
  2858. props.c_id = $course_id AND
  2859. docs.c_id = $course_id AND
  2860. props.tool = '".TOOL_DOCUMENT."' AND
  2861. props.visibility <> 2
  2862. $group_condition
  2863. $session_condition
  2864. ";
  2865. $result = Database::query($sql);
  2866. if ($result && Database::num_rows($result) != 0) {
  2867. $row = Database::fetch_row($result);
  2868. return $row[0];
  2869. } else {
  2870. return 0;
  2871. }
  2872. }
  2873. /**
  2874. * Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
  2875. */
  2876. public static function display_quota($course_quota, $already_consumed_space)
  2877. {
  2878. $course_quota_m = round($course_quota / 1048576);
  2879. $already_consumed_space_m = round($already_consumed_space / 1048576);
  2880. $message = get_lang('MaximumAllowedQuota').' <strong>'.$course_quota_m.' megabyte</strong>.<br />';
  2881. $message .= get_lang('CourseCurrentlyUses').' <strong>'.$already_consumed_space_m.' megabyte</strong>.<br />';
  2882. $percentage = round(($already_consumed_space / $course_quota * 100), 1);
  2883. $other_percentage = $percentage < 100 ? 100 - $percentage : 0;
  2884. // Decide where to place percentage in graph
  2885. if ($percentage >= 50) {
  2886. $text_in_filled = '&nbsp;'.$other_percentage.'%';
  2887. $text_in_unfilled = '';
  2888. } else {
  2889. $text_in_unfilled = '&nbsp;'.$other_percentage.'%';
  2890. $text_in_filled = '';
  2891. }
  2892. // Decide the background colour of the graph
  2893. if ($percentage < 65) {
  2894. $colour = '#00BB00'; // Safe - green
  2895. } elseif ($percentage < 90) {
  2896. $colour = '#ffd400'; // Filling up - yelloworange
  2897. } else {
  2898. $colour = '#DD0000'; // Full - red
  2899. }
  2900. // This is used for the table width: a table of only 100 pixels looks too small
  2901. $visual_percentage = 4 * $percentage;
  2902. $visual_other_percentage = 4 * $other_percentage;
  2903. $message .= get_lang('PercentageQuotaInUse').': <strong>'.$percentage.'%</strong>.<br />'.
  2904. get_lang('PercentageQuotaFree').': <strong>'.$other_percentage.'%</strong>.<br />';
  2905. $show_percentage = '&nbsp;'.$percentage.'%';
  2906. $message .= '<div style="width: 80%; text-align: center; -moz-border-radius: 5px 5px 5px 5px; border: 1px solid #aaa; background-image: url(\''.api_get_path(WEB_CODE_PATH).'css/'.api_get_visual_theme().'/images/bg-header4.png\');" class="document-quota-bar">'.
  2907. '<div style="width:'.$percentage.'%; background-color: #bbb; border-right:3px groove #bbb; -moz-border-radius:5px;">&nbsp;</div>'.
  2908. '<span style="margin-top: -15px; margin-left:-15px; position: absolute;font-weight:bold;">'.$show_percentage.'</span></div>';
  2909. echo $message;
  2910. }
  2911. /**
  2912. * Display the document quota in a simple way
  2913. *
  2914. * Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
  2915. */
  2916. public static function display_simple_quota($course_quota, $already_consumed_space)
  2917. {
  2918. $course_quota_m = round($course_quota / 1048576);
  2919. $already_consumed_space_m = round($already_consumed_space / 1048576, 2);
  2920. $percentage = $already_consumed_space / $course_quota * 100;
  2921. $percentage = round($percentage, 1);
  2922. $message = get_lang('YouAreCurrentlyUsingXOfYourX');
  2923. $message = sprintf($message, $already_consumed_space_m, $percentage.'%', $course_quota_m.' ');
  2924. return Display::div($message, array('id' => 'document_quota'));
  2925. }
  2926. /**
  2927. * Checks if there is enough place to add a file on a directory
  2928. * on the base of a maximum directory size allowed
  2929. *
  2930. * @author Bert Vanderkimpen
  2931. * @param int $file_size size of the file in byte
  2932. * @param int $max_dir_space maximum size
  2933. * @return boolean true if there is enough space, false otherwise
  2934. *
  2935. * @see enough_space() uses documents_total_space() function
  2936. */
  2937. public static function enough_space($file_size, $max_dir_space)
  2938. {
  2939. if ($max_dir_space) {
  2940. $already_filled_space = self::documents_total_space();
  2941. if (($file_size + $already_filled_space) > $max_dir_space) {
  2942. return false;
  2943. }
  2944. }
  2945. return true;
  2946. }
  2947. /**
  2948. * @param array $params count, url, extension
  2949. * @return string
  2950. */
  2951. public static function generate_jplayer_jquery($params = array())
  2952. {
  2953. $js_path = api_get_path(WEB_LIBRARY_PATH).'javascript/';
  2954. $js = '
  2955. $("#jquery_jplayer_' . $params['count'].'").jPlayer({
  2956. ready: function() {
  2957. $(this).jPlayer("setMedia", {
  2958. ' . $params['extension'].' : "'.$params['url'].'"
  2959. });
  2960. },
  2961. play: function() { // To avoid both jPlayers playing together.
  2962. $(this).jPlayer("pauseOthers");
  2963. },
  2964. //errorAlerts: true,
  2965. //warningAlerts: true,
  2966. swfPath: "' . $js_path.'jquery-jplayer/jplayer/",
  2967. //supplied: "m4a, oga, mp3, ogg, wav",
  2968. supplied: "' . $params['extension'].'",
  2969. wmode: "window",
  2970. solution: "flash, html", // Do not change this setting
  2971. cssSelectorAncestor: "#jp_container_' . $params['count'].'",
  2972. }); ' . "\n\n";
  2973. return $js;
  2974. }
  2975. /**
  2976. *
  2977. * Shows a play icon next to the document title in the document list
  2978. * @param int
  2979. * @param string
  2980. * @return string html content
  2981. */
  2982. public static function generate_media_preview($i, $type = 'simple')
  2983. {
  2984. $i = intval($i);
  2985. $extra_controls = $progress = '';
  2986. if ($type == 'advanced') {
  2987. $extra_controls = ' <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
  2988. <li><a href="#" class="jp-mute" tabindex="1">mute</a></li>
  2989. <li><a href="#" class="jp-unmute" tabindex="1">unmute</a></li>';
  2990. $progress = '<div class="jp-progress">
  2991. <div class="jp-seek-bar">
  2992. <div class="jp-play-bar"></div>
  2993. </div>
  2994. </div>';
  2995. }
  2996. //Shows only the play button
  2997. $html = '<div id="jquery_jplayer_'.$i.'" class="jp-jplayer"></div>
  2998. <div id="jp_container_' . $i.'" class="jp-audio">
  2999. <div class="jp-type-single">
  3000. <div class="jp-gui jp-interface">
  3001. <ul class="jp-controls">
  3002. <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
  3003. <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
  3004. ' . $extra_controls.'
  3005. </ul>
  3006. ' . $progress.'
  3007. </div>
  3008. </div>
  3009. </div>';
  3010. //<div id="jplayer_inspector_'.$i.'"></div>
  3011. return $html;
  3012. }
  3013. /**
  3014. * @param array $document_data
  3015. * @return string
  3016. */
  3017. public static function generate_video_preview($document_data = array())
  3018. {
  3019. //<button class="jp-video-play-icon" role="button" tabindex="0">play</button>
  3020. $html = '
  3021. <div id="jp_container_1" class="jp-video center-block" role="application" aria-label="media player">
  3022. <div class="jp-type-single">
  3023. <div id="jquery_jplayer_1" class="jp-jplayer"></div>
  3024. <div class="jp-gui">
  3025. <div class="jp-video-play">
  3026. </div>
  3027. <div class="jp-interface">
  3028. <div class="jp-progress">
  3029. <div class="jp-seek-bar">
  3030. <div class="jp-play-bar"></div>
  3031. </div>
  3032. </div>
  3033. <div class="jp-current-time" role="timer" aria-label="time">&nbsp;</div>
  3034. <div class="jp-duration" role="timer" aria-label="duration">&nbsp;</div>
  3035. <div class="jp-controls-holder">
  3036. <div class="jp-controls">
  3037. <button class="jp-play" role="button" tabindex="0">play</button>
  3038. <button class="jp-stop" role="button" tabindex="0">stop</button>
  3039. </div>
  3040. <div class="jp-volume-controls">
  3041. <button class="jp-mute" role="button" tabindex="0">mute</button>
  3042. <button class="jp-volume-max" role="button" tabindex="0">max volume</button>
  3043. <div class="jp-volume-bar">
  3044. <div class="jp-volume-bar-value"></div>
  3045. </div>
  3046. </div>
  3047. <div class="jp-toggles">
  3048. <button class="jp-repeat" role="button" tabindex="0">repeat</button>
  3049. <button class="jp-full-screen" role="button" tabindex="0">full screen</button>
  3050. </div>
  3051. </div>
  3052. <div class="jp-details">
  3053. <div class="jp-title" aria-label="title">&nbsp;</div>
  3054. </div>
  3055. </div>
  3056. </div>
  3057. <div class="jp-no-solution">
  3058. <span>' . get_lang('UpdateRequire').'</span>
  3059. ' . get_lang("ToPlayTheMediaYouWillNeedToUpdateYourBrowserToARecentVersionYouCanAlsoDownloadTheFile").'
  3060. </div>
  3061. </div>
  3062. </div>';
  3063. return $html;
  3064. }
  3065. /**
  3066. * @param array $course_info
  3067. * @param bool $lp_id
  3068. * @param string $target
  3069. * @param int $session_id
  3070. * @param bool $add_move_button
  3071. * @param string $filter_by_folder
  3072. * @param string $overwrite_url
  3073. * @param bool $showInvisibleFiles
  3074. * @param bool $showOnlyFolders
  3075. * @param int $folderId
  3076. * @return string
  3077. */
  3078. public static function get_document_preview(
  3079. $course_info,
  3080. $lp_id = false,
  3081. $target = '',
  3082. $session_id = 0,
  3083. $add_move_button = false,
  3084. $filter_by_folder = null,
  3085. $overwrite_url = null,
  3086. $showInvisibleFiles = false,
  3087. $showOnlyFolders = false,
  3088. $folderId = false
  3089. ) {
  3090. if (empty($course_info['real_id']) || empty($course_info['code']) || !is_array($course_info)) {
  3091. return '';
  3092. }
  3093. $overwrite_url = Security::remove_XSS($overwrite_url);
  3094. $user_id = api_get_user_id();
  3095. $userInfo = api_get_user_info();
  3096. $user_in_course = false;
  3097. if (api_is_platform_admin()) {
  3098. $user_in_course = true;
  3099. }
  3100. if (!$user_in_course) {
  3101. if (CourseManager::is_course_teacher($user_id, $course_info['code'])) {
  3102. $user_in_course = true;
  3103. }
  3104. }
  3105. // Condition for the session
  3106. $session_id = intval($session_id);
  3107. if (!$user_in_course) {
  3108. if (empty($session_id)) {
  3109. if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) {
  3110. $user_in_course = true;
  3111. }
  3112. // Check if course is open then we can consider that the student is registered to the course
  3113. if (isset($course_info) && in_array($course_info['visibility'], array(2, 3))) {
  3114. $user_in_course = true;
  3115. }
  3116. } else {
  3117. $user_status = SessionManager::get_user_status_in_course_session(
  3118. $user_id,
  3119. $course_info['real_id'],
  3120. $session_id
  3121. );
  3122. //is true if is an student, course session teacher or coach
  3123. if (in_array($user_status, array('0', '2', '6'))) {
  3124. $user_in_course = true;
  3125. }
  3126. }
  3127. }
  3128. $tbl_doc = Database::get_course_table(TABLE_DOCUMENT);
  3129. $tbl_item_prop = Database::get_course_table(TABLE_ITEM_PROPERTY);
  3130. $condition_session = " AND (last.session_id = '$session_id' OR last.session_id = '0' OR last.session_id IS NULL)";
  3131. $add_folder_filter = null;
  3132. if (!empty($filter_by_folder)) {
  3133. $add_folder_filter = " AND docs.path LIKE '".Database::escape_string($filter_by_folder)."%'";
  3134. }
  3135. // If we are in LP display hidden folder https://support.chamilo.org/issues/6679
  3136. $lp_visibility_condition = null;
  3137. if ($lp_id) {
  3138. // $lp_visibility_condition = " OR filetype='folder'";
  3139. if ($showInvisibleFiles) {
  3140. $lp_visibility_condition .= ' OR last.visibility = 0';
  3141. }
  3142. }
  3143. $showOnlyFoldersCondition = null;
  3144. if ($showOnlyFolders) {
  3145. //$showOnlyFoldersCondition = " AND docs.filetype = 'folder' ";
  3146. }
  3147. $folderCondition = " AND docs.path LIKE '/%' ";
  3148. if (!api_is_allowed_to_edit()) {
  3149. $protectedFolders = self::getProtectedFolderFromStudent();
  3150. foreach ($protectedFolders as $folder) {
  3151. $folderCondition .= " AND docs.path NOT LIKE '$folder' ";
  3152. }
  3153. }
  3154. $parentData = [];
  3155. if ($folderId !== false) {
  3156. $parentData = self::get_document_data_by_id($folderId, $course_info['code'], false, $session_id);
  3157. if (!empty($parentData)) {
  3158. $cleanedPath = $parentData['path'];
  3159. $num = substr_count($cleanedPath, '/');
  3160. $notLikeCondition = null;
  3161. for ($i = 1; $i <= $num; $i++) {
  3162. $repeat = str_repeat('/%', $i + 1);
  3163. $notLikeCondition .= " AND docs.path NOT LIKE '".Database::escape_string($cleanedPath.$repeat)."' ";
  3164. }
  3165. $folderCondition = " AND
  3166. docs.id <> $folderId AND
  3167. docs.path LIKE '".$cleanedPath."/%'
  3168. $notLikeCondition
  3169. ";
  3170. } else {
  3171. $folderCondition = " AND
  3172. docs.filetype = 'file' ";
  3173. }
  3174. }
  3175. $levelCondition = null;
  3176. if ($folderId === false) {
  3177. $levelCondition = " AND docs.path NOT LIKE'/%/%'";
  3178. }
  3179. $sql = "SELECT DISTINCT last.visibility, docs.*
  3180. FROM $tbl_item_prop AS last INNER JOIN $tbl_doc AS docs
  3181. ON (docs.id = last.ref AND docs.c_id = last.c_id)
  3182. WHERE
  3183. docs.path NOT LIKE '%_DELETED_%' AND
  3184. last.tool = '".TOOL_DOCUMENT."' $condition_session AND
  3185. (last.visibility = '1' $lp_visibility_condition) AND
  3186. last.visibility <> 2 AND
  3187. docs.c_id = {$course_info['real_id']} AND
  3188. last.c_id = {$course_info['real_id']}
  3189. $showOnlyFoldersCondition
  3190. $folderCondition
  3191. $levelCondition
  3192. $add_folder_filter
  3193. ORDER BY docs.filetype DESC, docs.title ASC";
  3194. $res_doc = Database::query($sql);
  3195. $resources = Database::store_result($res_doc, 'ASSOC');
  3196. $return = '';
  3197. if ($lp_id) {
  3198. if ($folderId === false) {
  3199. /*$return .= '<div class="lp_resource_element">';
  3200. $return .= Display::return_icon('new_doc.gif', '', array(), ICON_SIZE_SMALL);
  3201. $return .= Display::url(
  3202. get_lang('CreateTheDocument'),
  3203. api_get_self().'?'.api_get_cidreq().'&action=add_item&type='.TOOL_DOCUMENT.'&lp_id='.$_SESSION['oLP']->lp_id
  3204. );
  3205. $return .= '</div>';*/
  3206. }
  3207. } else {
  3208. $return .= Display::div(
  3209. Display::url(
  3210. Display::return_icon('close.png', get_lang('Close'), array(), ICON_SIZE_SMALL),
  3211. ' javascript:void(0);',
  3212. array('id' => 'close_div_'.$course_info['real_id'].'_'.$session_id, 'class' => 'close_div')
  3213. ),
  3214. array('style' => 'position:absolute;right:10px')
  3215. );
  3216. }
  3217. // If you want to debug it, I advise you to do "echo" on the eval statements.
  3218. $newResources = array();
  3219. if (!empty($resources) && $user_in_course) {
  3220. foreach ($resources as $resource) {
  3221. $is_visible = self::is_visible_by_id(
  3222. $resource['id'],
  3223. $course_info,
  3224. $session_id,
  3225. api_get_user_id()
  3226. );
  3227. if ($showInvisibleFiles == false) {
  3228. if (!$is_visible) {
  3229. continue;
  3230. }
  3231. }
  3232. $newResources[] = $resource;
  3233. }
  3234. }
  3235. $label = get_lang('Documents');
  3236. $documents = [];
  3237. if ($folderId === false) {
  3238. $documents[$label] = array(
  3239. 'id' => 0,
  3240. 'files' => $newResources
  3241. );
  3242. } else {
  3243. if (is_array($parentData)) {
  3244. $documents[$parentData['title']] = array(
  3245. 'id' => intval($folderId),
  3246. 'files' => $newResources
  3247. );
  3248. }
  3249. }
  3250. $write_result = self::write_resources_tree(
  3251. $userInfo,
  3252. $course_info,
  3253. $session_id,
  3254. $documents,
  3255. $lp_id,
  3256. $target,
  3257. $add_move_button,
  3258. $overwrite_url,
  3259. $folderId
  3260. );
  3261. $return .= $write_result;
  3262. if ($lp_id == false) {
  3263. $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&url='.$overwrite_url.'&lp_id='.$lp_id.'&cidReq='.$course_info['code'];
  3264. $return .= "<script>
  3265. $('.doc_folder').click(function() {
  3266. var realId = this.id;
  3267. var my_id = this.id.split('_')[2];
  3268. var tempId = 'temp_'+my_id;
  3269. $('#res_'+my_id).show();
  3270. var tempDiv = $('#'+realId).find('#'+tempId);
  3271. if (tempDiv.length == 0) {
  3272. $.ajax({
  3273. async: false,
  3274. type: 'GET',
  3275. url: '".$url."',
  3276. data: 'folder_id='+my_id,
  3277. success: function(data) {
  3278. $('#'+realId).append('<div id='+tempId+'>'+data+'</div>');
  3279. }
  3280. });
  3281. }
  3282. });
  3283. $('.close_div').click(function() {
  3284. var course_id = this.id.split('_')[2];
  3285. var session_id = this.id.split('_')[3];
  3286. $('#document_result_'+course_id+'_'+session_id).hide();
  3287. $('.lp_resource').remove();
  3288. $('.document_preview_container').html('');
  3289. });
  3290. </script>";
  3291. } else {
  3292. //For LPs
  3293. $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&lp_id='.$lp_id.'&'.api_get_cidreq();
  3294. $return .= "<script>
  3295. function testResources(id, img) {
  3296. var numericId = id.split('_')[1];
  3297. var parentId = 'doc_id_'+numericId;
  3298. var tempId = 'temp_'+numericId;
  3299. var image = $('#'+img);
  3300. if (image.hasClass('open')) {
  3301. image.removeClass('open');
  3302. image.attr('src', '" . Display::returnIconPath('nolines_plus.gif')."');
  3303. $('#'+id).show();
  3304. $('#'+tempId).hide();
  3305. } else {
  3306. image.addClass('open');
  3307. image.attr('src', '" . Display::returnIconPath('nolines_minus.gif')."');
  3308. $('#'+id).hide();
  3309. $('#'+tempId).show();
  3310. var tempDiv = $('#'+parentId).find('#'+tempId);
  3311. if (tempDiv.length == 0) {
  3312. $.ajax({
  3313. type: 'GET',
  3314. async: false,
  3315. url: '".$url."',
  3316. data: 'folder_id='+numericId,
  3317. success: function(data) {
  3318. tempDiv = $('#doc_id_'+numericId).append('<div id='+tempId+'>'+data+'</div>');
  3319. }
  3320. });
  3321. }
  3322. }
  3323. }
  3324. </script>";
  3325. }
  3326. if (!$user_in_course) {
  3327. $return = '';
  3328. }
  3329. return $return;
  3330. }
  3331. /**
  3332. * Parse file information into a link
  3333. *
  3334. * @param array $userInfo Current user info
  3335. * @param array $course_info
  3336. * @param int $session_id
  3337. * @param array $resource
  3338. * @param int $lp_id
  3339. * @param bool $add_move_button
  3340. * @param string $target
  3341. * @param string $overwrite_url
  3342. * @return null|string
  3343. */
  3344. private static function parseFile(
  3345. $userInfo,
  3346. $course_info,
  3347. $session_id,
  3348. $resource,
  3349. $lp_id,
  3350. $add_move_button,
  3351. $target,
  3352. $overwrite_url
  3353. ) {
  3354. $img_sys_path = api_get_path(SYS_CODE_PATH).'img/';
  3355. $web_code_path = api_get_path(WEB_CODE_PATH);
  3356. $documentId = $resource['id'];
  3357. $path = $resource['path'];
  3358. if (empty($path)) {
  3359. $num = 0;
  3360. } else {
  3361. $num = substr_count($path, '/') - 1;
  3362. }
  3363. // It's a file.
  3364. $icon = choose_image($path);
  3365. $position = strrpos($icon, '.');
  3366. $icon = substr($icon, 0, $position).'_small.gif';
  3367. $my_file_title = $resource['title'];
  3368. $visibility = $resource['visibility'];
  3369. // If title is empty we try to use the path
  3370. if (empty($my_file_title)) {
  3371. $my_file_title = basename($path);
  3372. }
  3373. // Show the "image name" not the filename of the image.
  3374. if ($lp_id) {
  3375. // LP URL
  3376. $url = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.api_get_cidreq().'&amp;action=add_item&amp;type='.TOOL_DOCUMENT.'&amp;file='.$documentId.'&amp;lp_id='.$lp_id;
  3377. if (!empty($overwrite_url)) {
  3378. $url = $overwrite_url.'&cidReq='.$course_info['code'].'&id_session='.$session_id.'&document_id='.$documentId.'';
  3379. }
  3380. } else {
  3381. // Direct document URL
  3382. $url = $web_code_path.'document/document.php?cidReq='.$course_info['code'].'&id_session='.$session_id.'&id='.$documentId;
  3383. if (!empty($overwrite_url)) {
  3384. $url = $overwrite_url.'&cidReq='.$course_info['code'].'&id_session='.$session_id.'&document_id='.$documentId;
  3385. }
  3386. }
  3387. $img = Display::returnIconPath($icon);
  3388. if (!file_exists($img_sys_path.$icon)) {
  3389. $img = Display::returnIconPath('default_small.gif');
  3390. }
  3391. $link = Display::url(
  3392. '<img alt="" src="'.$img.'" title="" />&nbsp;'.$my_file_title, $url,
  3393. array('target' => $target, 'class' => 'moved')
  3394. );
  3395. $directUrl = $web_code_path.'document/document.php?cidReq='.$course_info['code'].'&id_session='.$session_id.'&id='.$documentId;
  3396. $link .= Display::url(
  3397. Display::return_icon('preview_view.png', get_lang('Preview')),
  3398. $directUrl,
  3399. ['target' => '_blank']
  3400. );
  3401. $visibilityClass = null;
  3402. if ($visibility == 0) {
  3403. $visibilityClass = ' text-muted ';
  3404. }
  3405. $return = null;
  3406. if ($lp_id == false) {
  3407. $return .= '<li class="doc_resource '.$visibilityClass.' " data_id="'.$documentId.'" data_type="document" title="'.$my_file_title.'" >';
  3408. } else {
  3409. $return .= '<li class="doc_resource lp_resource_element '.$visibilityClass.' " data_id="'.$documentId.'" data_type="document" title="'.$my_file_title.'" >';
  3410. }
  3411. $return .= '<div class="item_data" style="margin-left:'.($num * 5).'px;margin-right:5px;">';
  3412. if ($add_move_button) {
  3413. $return .= '<a class="moved" href="#">';
  3414. $return .= Display::return_icon('move_everywhere.png', get_lang('Move'), array(), ICON_SIZE_TINY);
  3415. $return .= '</a> ';
  3416. }
  3417. $return .= $link;
  3418. $sessionStar = api_get_session_image($resource['session_id'], $userInfo['status']);
  3419. $return .= $sessionStar;
  3420. $return .= '</div></li>';
  3421. return $return;
  3422. }
  3423. /**
  3424. * @param int $folderId
  3425. * @param array $resource
  3426. * @param int $lp_id
  3427. * @return null|string
  3428. */
  3429. private static function parseFolder($folderId, $resource, $lp_id)
  3430. {
  3431. $title = isset($resource['title']) ? $resource['title'] : null;
  3432. $path = isset($resource['path']) ? $resource['path'] : null;
  3433. if (empty($path)) {
  3434. $num = 0;
  3435. } else {
  3436. $num = substr_count($path, '/');
  3437. }
  3438. // It's a folder.
  3439. //hide some folders
  3440. if (in_array($path,
  3441. array('shared_folder', 'chat_files', 'HotPotatoes_files', 'css', 'certificates'))) {
  3442. return null;
  3443. } elseif (preg_match('/_groupdocs/', $path)) {
  3444. return null;
  3445. } elseif (preg_match('/sf_user_/', $path)) {
  3446. return null;
  3447. } elseif (preg_match('/shared_folder_session_/', $path)) {
  3448. return null;
  3449. }
  3450. //trad some titles
  3451. /*
  3452. if ($key == 'images') {
  3453. $key = get_lang('Images');
  3454. } elseif ($key == 'gallery') {
  3455. $key = get_lang('Gallery');
  3456. } elseif ($key == 'flash') {
  3457. $key = get_lang('Flash');
  3458. } elseif ($key == 'audio') {
  3459. $key = get_lang('Audio');
  3460. } elseif ($key == 'video') {
  3461. $key = get_lang('Video');
  3462. }*/
  3463. $onclick = '';
  3464. // if in LP, hidden folder are displayed in grey
  3465. $folder_class_hidden = "";
  3466. if ($lp_id) {
  3467. if (isset($resource['visible']) && $resource['visible'] == 0) {
  3468. $folder_class_hidden = "doc_folder_hidden"; // in base.css
  3469. }
  3470. $onclick = 'onclick="javascript: testResources(\'res_'.$resource['id'].'\',\'img_'.$resource['id'].'\')"';
  3471. }
  3472. $return = null;
  3473. if (empty($path)) {
  3474. $return = '<ul class="lp_resource">';
  3475. }
  3476. $return .= '<li class="doc_folder '.$folder_class_hidden.'" id="doc_id_'.$resource['id'].'" style="margin-left:'.($num * 18).'px; ">';
  3477. $image = Display::returnIconPath('nolines_plus.gif');
  3478. if (empty($path)) {
  3479. $image = Display::returnIconPath('nolines_minus.gif');
  3480. }
  3481. $return .= '<img style="cursor: pointer;" src="'.$image.'" align="absmiddle" id="img_'.$resource['id'].'" '.$onclick.'>';
  3482. $return .= Display::return_icon('lp_folder.gif').'&nbsp;';
  3483. $return .= '<span '.$onclick.' style="cursor: pointer;" >'.$title.'</span>';
  3484. $return .= '</li>';
  3485. if (empty($path)) {
  3486. if ($folderId == false) {
  3487. $return .= '<div id="res_'.$resource['id'].'" >';
  3488. } else {
  3489. $return .= '<div id="res_'.$resource['id'].'" style="display: none;" >';
  3490. }
  3491. }
  3492. return $return;
  3493. }
  3494. /**
  3495. * Generate and return an HTML list of resources based on a given array.
  3496. * This list is used to show the course creator a list of available resources to choose from
  3497. * when creating a learning path.
  3498. * @param array $userInfo current user info
  3499. * @param array $course_info
  3500. * @param int $session_id
  3501. * @param array $documents
  3502. * @param bool $lp_id
  3503. * @param string $target
  3504. * @param bool $add_move_button
  3505. * @param string $overwrite_url
  3506. * @param int $folderId
  3507. *
  3508. * @return string
  3509. */
  3510. public static function write_resources_tree(
  3511. $userInfo,
  3512. $course_info,
  3513. $session_id,
  3514. $documents,
  3515. $lp_id = false,
  3516. $target = '',
  3517. $add_move_button = false,
  3518. $overwrite_url = null,
  3519. $folderId = false
  3520. ) {
  3521. $return = '';
  3522. if (!empty($documents)) {
  3523. foreach ($documents as $key => $resource) {
  3524. if (isset($resource['id']) && is_int($resource['id'])) {
  3525. $mainFolderResource = array(
  3526. 'id' => $resource['id'],
  3527. 'title' => $key,
  3528. );
  3529. if ($folderId === false) {
  3530. $return .= self::parseFolder($folderId, $mainFolderResource, $lp_id);
  3531. }
  3532. if (isset($resource['files'])) {
  3533. $return .= self::write_resources_tree(
  3534. $userInfo,
  3535. $course_info,
  3536. $session_id,
  3537. $resource['files'],
  3538. $lp_id,
  3539. $target,
  3540. $add_move_button,
  3541. $overwrite_url
  3542. );
  3543. }
  3544. $return .= '</div>';
  3545. $return .= '</ul>';
  3546. } else {
  3547. if ($resource['filetype'] == 'folder') {
  3548. $return .= self::parseFolder($folderId, $resource, $lp_id);
  3549. } else {
  3550. $return .= self::parseFile(
  3551. $userInfo,
  3552. $course_info,
  3553. $session_id,
  3554. $resource,
  3555. $lp_id,
  3556. $add_move_button,
  3557. $target,
  3558. $overwrite_url
  3559. );
  3560. }
  3561. }
  3562. }
  3563. }
  3564. return $return;
  3565. }
  3566. /**
  3567. * @param int $doc_id
  3568. * @param string $course_code
  3569. * @param int $session_id
  3570. * @param int $user_id
  3571. * @param int $groupId iid
  3572. * @return bool
  3573. */
  3574. public static function check_visibility_tree(
  3575. $doc_id,
  3576. $course_code,
  3577. $session_id,
  3578. $user_id,
  3579. $groupId = 0
  3580. ) {
  3581. $document_data = self::get_document_data_by_id($doc_id, $course_code, null, $session_id);
  3582. if ($session_id != 0 && !$document_data) {
  3583. $document_data = self::get_document_data_by_id($doc_id, $course_code, null, 0);
  3584. }
  3585. if (!empty($document_data)) {
  3586. // If admin or course teacher, allow anyway
  3587. if (api_is_platform_admin() || CourseManager::is_course_teacher($user_id, $course_code)) {
  3588. return true;
  3589. }
  3590. $course_info = api_get_course_info($course_code);
  3591. if ($document_data['parent_id'] == false || empty($document_data['parent_id'])) {
  3592. if (!empty($groupId)) {
  3593. return true;
  3594. }
  3595. $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
  3596. return $visible;
  3597. } else {
  3598. $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
  3599. if (!$visible) {
  3600. return false;
  3601. } else {
  3602. return self::check_visibility_tree(
  3603. $document_data['parent_id'],
  3604. $course_code,
  3605. $session_id,
  3606. $user_id,
  3607. $groupId
  3608. );
  3609. }
  3610. }
  3611. } else {
  3612. return false;
  3613. }
  3614. }
  3615. /**
  3616. * Index a given document.
  3617. * @param int Document ID inside its corresponding course
  3618. * @param string Course code
  3619. * @param int Session ID (not used yet)
  3620. * @param string Language of document's content (defaults to course language)
  3621. * @param array Array of specific fields (['code'=>'value',...])
  3622. * @param string What to do if the file already exists (default or overwrite)
  3623. * @param bool When set to true, this runs the indexer without actually saving anything to any database
  3624. * @return bool Returns true on presumed success, false on failure
  3625. */
  3626. public static function index_document(
  3627. $docid,
  3628. $course_code,
  3629. $session_id = 0,
  3630. $lang = 'english',
  3631. $specific_fields_values = array(),
  3632. $if_exists = '',
  3633. $simulation = false
  3634. ) {
  3635. if (api_get_setting('search_enabled') !== 'true') {
  3636. return false;
  3637. }
  3638. if (empty($docid) or $docid != intval($docid)) {
  3639. return false;
  3640. }
  3641. if (empty($session_id)) {
  3642. $session_id = api_get_session_id();
  3643. }
  3644. $course_info = api_get_course_info($course_code);
  3645. $course_dir = $course_info['path'].'/document';
  3646. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  3647. $base_work_dir = $sys_course_path.$course_dir;
  3648. $course_id = $course_info['real_id'];
  3649. $table_document = Database::get_course_table(TABLE_DOCUMENT);
  3650. $qry = "SELECT path, title FROM $table_document WHERE c_id = $course_id AND id = '$docid' LIMIT 1";
  3651. $result = Database::query($qry);
  3652. if (Database::num_rows($result) == 1) {
  3653. $row = Database::fetch_array($result);
  3654. $doc_path = api_get_path(SYS_COURSE_PATH).$course_dir.$row['path'];
  3655. //TODO: mime_content_type is deprecated, fileinfo php extension is enabled by default as of PHP 5.3.0
  3656. // now versions of PHP on Debian testing(5.2.6-5) and Ubuntu(5.2.6-2ubuntu) are lower, so wait for a while
  3657. $doc_mime = mime_content_type($doc_path);
  3658. $allowed_mime_types = self::file_get_mime_type(true);
  3659. // mime_content_type does not detect correctly some formats that are going to be supported for index, so an extensions array is used for the moment
  3660. if (empty($doc_mime)) {
  3661. $allowed_extensions = array('doc', 'docx', 'ppt', 'pptx', 'pps', 'ppsx', 'xls', 'xlsx', 'odt', 'odp', 'ods', 'pdf', 'txt', 'rtf', 'msg', 'csv', 'html', 'htm');
  3662. $extensions = preg_split("/[\/\\.]/", $doc_path);
  3663. $doc_ext = strtolower($extensions[count($extensions) - 1]);
  3664. if (in_array($doc_ext, $allowed_extensions)) {
  3665. switch ($doc_ext) {
  3666. case 'ppt':
  3667. case 'pps':
  3668. $doc_mime = 'application/vnd.ms-powerpoint';
  3669. break;
  3670. case 'xls':
  3671. $doc_mime = 'application/vnd.ms-excel';
  3672. break;
  3673. }
  3674. }
  3675. }
  3676. //@todo move this nightmare in a search controller or something like that!!! J.M
  3677. if (in_array($doc_mime, $allowed_mime_types)) {
  3678. $file_title = $row['title'];
  3679. $file_content = self::get_text_content($doc_path, $doc_mime);
  3680. $course_code = Database::escape_string($course_code);
  3681. require_once api_get_path(LIBRARY_PATH).'search/ChamiloIndexer.class.php';
  3682. require_once api_get_path(LIBRARY_PATH).'search/IndexableChunk.class.php';
  3683. $ic_slide = new IndexableChunk();
  3684. $ic_slide->addValue('title', $file_title);
  3685. $ic_slide->addCourseId($course_code);
  3686. $ic_slide->addToolId(TOOL_DOCUMENT);
  3687. $xapian_data = array(
  3688. SE_COURSE_ID => $course_code,
  3689. SE_TOOL_ID => TOOL_DOCUMENT,
  3690. SE_DATA => array('doc_id' => $docid),
  3691. SE_USER => api_get_user_id(),
  3692. );
  3693. $ic_slide->xapian_data = serialize($xapian_data);
  3694. $di = new ChamiloIndexer();
  3695. $return = $di->connectDb(null, null, $lang);
  3696. require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
  3697. $specific_fields = get_specific_field_list();
  3698. // process different depending on what to do if file exists
  3699. /**
  3700. * @TODO Find a way to really verify if the file had been
  3701. * overwriten. Now all work is done at
  3702. * handle_uploaded_document() and it's difficult to verify it
  3703. */
  3704. if (!empty($if_exists) && $if_exists == 'overwrite') {
  3705. // Overwrite the file on search engine
  3706. // Actually, it consists on a delete of terms from db,
  3707. // insert new ones, create a new search engine document,
  3708. // and remove the old one
  3709. // Get search_did
  3710. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  3711. $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  3712. $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid);
  3713. $res = Database::query($sql);
  3714. if (Database::num_rows($res) > 0) {
  3715. $se_ref = Database::fetch_array($res);
  3716. if (!$simulation) {
  3717. $di->remove_document($se_ref['search_did']);
  3718. }
  3719. $all_specific_terms = '';
  3720. foreach ($specific_fields as $specific_field) {
  3721. if (!$simulation) {
  3722. delete_all_specific_field_value($course_code, $specific_field['id'], TOOL_DOCUMENT, $docid);
  3723. }
  3724. // Update search engine
  3725. if (isset($specific_fields_values[$specific_field['code']])) {
  3726. $sterms = trim($specific_fields_values[$specific_field['code']]);
  3727. } else { //if the specific field is not defined, force an empty one
  3728. $sterms = '';
  3729. }
  3730. $all_specific_terms .= ' '.$sterms;
  3731. $sterms = explode(',', $sterms);
  3732. foreach ($sterms as $sterm) {
  3733. $sterm = trim($sterm);
  3734. if (!empty($sterm)) {
  3735. $ic_slide->addTerm($sterm, $specific_field['code']);
  3736. // updated the last param here from $value to $sterm without being sure - see commit15464
  3737. if (!$simulation) {
  3738. add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
  3739. }
  3740. }
  3741. }
  3742. }
  3743. // Add terms also to content to make terms findable by probabilistic search
  3744. $file_content = $all_specific_terms.' '.$file_content;
  3745. if (!$simulation) {
  3746. $ic_slide->addValue('content', $file_content);
  3747. $di->addChunk($ic_slide);
  3748. // Index and return a new search engine document id
  3749. $did = $di->index();
  3750. if ($did) {
  3751. // update the search_did on db
  3752. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  3753. $sql = 'UPDATE %s SET search_did=%d WHERE id=%d LIMIT 1';
  3754. $sql = sprintf($sql, $tbl_se_ref, (int) $did, (int) $se_ref['id']);
  3755. Database::query($sql);
  3756. }
  3757. }
  3758. }
  3759. } else {
  3760. // Add all terms
  3761. $all_specific_terms = '';
  3762. foreach ($specific_fields as $specific_field) {
  3763. if (isset($specific_fields_values[$specific_field['code']])) {
  3764. $sterms = trim($specific_fields_values[$specific_field['code']]);
  3765. } else { //if the specific field is not defined, force an empty one
  3766. $sterms = '';
  3767. }
  3768. $all_specific_terms .= ' '.$sterms;
  3769. if (!empty($sterms)) {
  3770. $sterms = explode(',', $sterms);
  3771. foreach ($sterms as $sterm) {
  3772. if (!$simulation) {
  3773. $ic_slide->addTerm(trim($sterm), $specific_field['code']);
  3774. add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
  3775. }
  3776. }
  3777. }
  3778. }
  3779. // Add terms also to content to make terms findable by probabilistic search
  3780. $file_content = $all_specific_terms.' '.$file_content;
  3781. if (!$simulation) {
  3782. $ic_slide->addValue('content', $file_content);
  3783. $di->addChunk($ic_slide);
  3784. // Index and return search engine document id
  3785. $did = $di->index();
  3786. if ($did) {
  3787. // Save it to db
  3788. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  3789. $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
  3790. VALUES (NULL , \'%s\', \'%s\', %s, %s)';
  3791. $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid, $did);
  3792. Database::query($sql);
  3793. } else {
  3794. return false;
  3795. }
  3796. }
  3797. }
  3798. } else {
  3799. return false;
  3800. }
  3801. }
  3802. return true;
  3803. }
  3804. /**
  3805. * @return array
  3806. */
  3807. public static function get_web_odf_extension_list()
  3808. {
  3809. return array('ods', 'odt', 'odp');
  3810. }
  3811. /**
  3812. * Set of extension allowed to use Jodconverter
  3813. * @param $mode 'from'
  3814. * 'to'
  3815. * 'all'
  3816. * @param $format 'text'
  3817. * 'spreadsheet'
  3818. * 'presentation'
  3819. * 'drawing'
  3820. * 'all'
  3821. * @return array
  3822. */
  3823. public static function getJodconverterExtensionList($mode, $format)
  3824. {
  3825. $extensionList = array();
  3826. $extensionListFromText = array(
  3827. 'odt',
  3828. 'sxw',
  3829. 'rtf',
  3830. 'doc',
  3831. 'docx',
  3832. 'wpd',
  3833. 'txt',
  3834. );
  3835. $extensionListToText = array(
  3836. 'pdf',
  3837. 'odt',
  3838. 'sxw',
  3839. 'rtf',
  3840. 'doc',
  3841. 'docx',
  3842. 'txt',
  3843. );
  3844. $extensionListFromSpreadsheet = array(
  3845. 'ods',
  3846. 'sxc',
  3847. 'xls',
  3848. 'xlsx',
  3849. 'csv',
  3850. 'tsv',
  3851. );
  3852. $extensionListToSpreadsheet = array(
  3853. 'pdf',
  3854. 'ods',
  3855. 'sxc',
  3856. 'xls',
  3857. 'xlsx',
  3858. 'csv',
  3859. 'tsv',
  3860. );
  3861. $extensionListFromPresentation = array(
  3862. 'odp',
  3863. 'sxi',
  3864. 'ppt',
  3865. 'pptx',
  3866. );
  3867. $extensionListToPresentation = array(
  3868. 'pdf',
  3869. 'swf',
  3870. 'odp',
  3871. 'sxi',
  3872. 'ppt',
  3873. 'pptx',
  3874. );
  3875. $extensionListFromDrawing = array('odg');
  3876. $extensionListToDrawing = array('svg', 'swf');
  3877. if ($mode === 'from') {
  3878. if ($format === 'text') {
  3879. $extensionList = array_merge($extensionList, $extensionListFromText);
  3880. } elseif ($format === 'spreadsheet') {
  3881. $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
  3882. } elseif ($format === 'presentation') {
  3883. $extensionList = array_merge($extensionList, $extensionListFromPresentation);
  3884. } elseif ($format === 'drawing') {
  3885. $extensionList = array_merge($extensionList, $extensionListFromDrawing);
  3886. } elseif ($format === 'all') {
  3887. $extensionList = array_merge($extensionList, $extensionListFromText);
  3888. $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
  3889. $extensionList = array_merge($extensionList, $extensionListFromPresentation);
  3890. $extensionList = array_merge($extensionList, $extensionListFromDrawing);
  3891. }
  3892. } elseif ($mode === 'to') {
  3893. if ($format === 'text') {
  3894. $extensionList = array_merge($extensionList, $extensionListToText);
  3895. } elseif ($format === 'spreadsheet') {
  3896. $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
  3897. } elseif ($format === 'presentation') {
  3898. $extensionList = array_merge($extensionList, $extensionListToPresentation);
  3899. } elseif ($format === 'drawing') {
  3900. $extensionList = array_merge($extensionList, $extensionListToDrawing);
  3901. } elseif ($format === 'all') {
  3902. $extensionList = array_merge($extensionList, $extensionListToText);
  3903. $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
  3904. $extensionList = array_merge($extensionList, $extensionListToPresentation);
  3905. $extensionList = array_merge($extensionList, $extensionListToDrawing);
  3906. }
  3907. } elseif ($mode === 'all') {
  3908. if ($format === 'text') {
  3909. $extensionList = array_merge($extensionList, $extensionListFromText);
  3910. $extensionList = array_merge($extensionList, $extensionListToText);
  3911. } elseif ($format === 'spreadsheet') {
  3912. $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
  3913. $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
  3914. } elseif ($format === 'presentation') {
  3915. $extensionList = array_merge($extensionList, $extensionListFromPresentation);
  3916. $extensionList = array_merge($extensionList, $extensionListToPresentation);
  3917. } elseif ($format === 'drawing') {
  3918. $extensionList = array_merge($extensionList, $extensionListFromDrawing);
  3919. $extensionList = array_merge($extensionList, $extensionListToDrawing);
  3920. } elseif ($format === 'all') {
  3921. $extensionList = array_merge($extensionList, $extensionListFromText);
  3922. $extensionList = array_merge($extensionList, $extensionListToText);
  3923. $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
  3924. $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
  3925. $extensionList = array_merge($extensionList, $extensionListFromPresentation);
  3926. $extensionList = array_merge($extensionList, $extensionListToPresentation);
  3927. $extensionList = array_merge($extensionList, $extensionListFromDrawing);
  3928. $extensionList = array_merge($extensionList, $extensionListToDrawing);
  3929. }
  3930. }
  3931. return $extensionList;
  3932. }
  3933. /**
  3934. * Get Format type list by extension and mode
  3935. * @param string $mode Mode to search format type list
  3936. * @example 'from'
  3937. * @example 'to'
  3938. * @param string $extension file extension to check file type
  3939. * @return array
  3940. */
  3941. public static function getFormatTypeListConvertor($mode = 'from', $extension)
  3942. {
  3943. $formatTypesList = array();
  3944. $formatTypes = array('text', 'spreadsheet', 'presentation', 'drawing');
  3945. foreach ($formatTypes as $formatType) {
  3946. if (
  3947. in_array(
  3948. $extension,
  3949. self::getJodconverterExtensionList($mode, $formatType)
  3950. )
  3951. ) {
  3952. $formatTypesList[] = $formatType;
  3953. }
  3954. }
  3955. return $formatTypesList;
  3956. }
  3957. /**
  3958. * @param string $path
  3959. * @param bool $is_certificate_mode
  3960. * @return bool
  3961. */
  3962. public static function is_folder_to_avoid($path, $is_certificate_mode = false)
  3963. {
  3964. $foldersToAvoid = array(
  3965. '/HotPotatoes_files',
  3966. '/certificates',
  3967. );
  3968. $systemFolder = api_get_course_setting('show_system_folders');
  3969. if ($systemFolder == 1) {
  3970. $foldersToAvoid = array();
  3971. }
  3972. if (basename($path) == 'css') {
  3973. return true;
  3974. }
  3975. if ($is_certificate_mode == false) {
  3976. //Certificate results
  3977. if (strstr($path, 'certificates')) {
  3978. return true;
  3979. }
  3980. }
  3981. // Admin setting for Hide/Show the folders of all users
  3982. if (api_get_setting('show_users_folders') == 'false') {
  3983. $foldersToAvoid[] = '/shared_folder';
  3984. if (strstr($path, 'shared_folder_session_')) {
  3985. return true;
  3986. }
  3987. }
  3988. // Admin setting for Hide/Show Default folders to all users
  3989. if (api_get_setting('show_default_folders') == 'false') {
  3990. $foldersToAvoid[] = '/images';
  3991. $foldersToAvoid[] = '/flash';
  3992. $foldersToAvoid[] = '/audio';
  3993. $foldersToAvoid[] = '/video';
  3994. }
  3995. // Admin setting for Hide/Show chat history folder
  3996. if (api_get_setting('show_chat_folder') == 'false') {
  3997. $foldersToAvoid[] = '/chat_files';
  3998. }
  3999. if (is_array($foldersToAvoid)) {
  4000. return in_array($path, $foldersToAvoid);
  4001. } else {
  4002. return false;
  4003. }
  4004. }
  4005. /**
  4006. * @return array
  4007. */
  4008. public static function get_system_folders()
  4009. {
  4010. return array(
  4011. '/certificates',
  4012. '/HotPotatoes_files',
  4013. '/chat_files',
  4014. '/images',
  4015. '/flash',
  4016. '/audio',
  4017. '/video',
  4018. '/shared_folder',
  4019. '/learning_path'
  4020. );
  4021. }
  4022. /**
  4023. * @return array
  4024. */
  4025. public static function getProtectedFolderFromStudent()
  4026. {
  4027. return array(
  4028. '/certificates',
  4029. '/HotPotatoes_files',
  4030. '/chat_files',
  4031. '/shared_folder',
  4032. '/learning_path'
  4033. );
  4034. }
  4035. /**
  4036. * @param string $courseCode
  4037. * @return string 'visible' or 'invisible' string
  4038. */
  4039. public static function getDocumentDefaultVisibility($courseCode)
  4040. {
  4041. $settings = api_get_setting('tool_visible_by_default_at_creation');
  4042. $defaultVisibility = 'visible';
  4043. if (isset($settings['documents'])) {
  4044. $portalDefaultVisibility = 'invisible';
  4045. if ($settings['documents'] == 'true') {
  4046. $portalDefaultVisibility = 'visible';
  4047. }
  4048. $defaultVisibility = $portalDefaultVisibility;
  4049. }
  4050. if (api_get_setting('documents_default_visibility_defined_in_course') == 'true') {
  4051. $courseVisibility = api_get_course_setting('documents_default_visibility', $courseCode);
  4052. if (!empty($courseVisibility) && in_array($courseVisibility, array('visible', 'invisible'))) {
  4053. $defaultVisibility = $courseVisibility;
  4054. }
  4055. }
  4056. return $defaultVisibility;
  4057. }
  4058. /**
  4059. * @param array $courseInfo
  4060. * @param int $id doc id
  4061. * @param string $visibility visible/invisible
  4062. * @param int $userId
  4063. */
  4064. public static function updateVisibilityFromAllSessions($courseInfo, $id, $visibility, $userId)
  4065. {
  4066. $sessionList = SessionManager::get_session_by_course($courseInfo['real_id']);
  4067. if (!empty($sessionList)) {
  4068. foreach ($sessionList as $session) {
  4069. $sessionId = $session['id'];
  4070. api_item_property_update(
  4071. $courseInfo,
  4072. TOOL_DOCUMENT,
  4073. $id,
  4074. $visibility,
  4075. $userId,
  4076. null,
  4077. null,
  4078. null,
  4079. null,
  4080. $sessionId
  4081. );
  4082. }
  4083. }
  4084. }
  4085. /**
  4086. * @param string $file
  4087. * @return string
  4088. */
  4089. public static function readNanogongFile($file)
  4090. {
  4091. $nanoGongJarFile = api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar';
  4092. $html = '<applet id="applet" archive="'.$nanoGongJarFile.'" code="gong.NanoGong" width="160" height="95">';
  4093. $html .= '<param name="SoundFileURL" value="'.$file.'" />';
  4094. $html .= '<param name="ShowSaveButton" value="false" />';
  4095. $html .= '<param name="ShowTime" value="true" />';
  4096. $html .= '<param name="ShowRecordButton" value="false" />';
  4097. $html .= '</applet>';
  4098. return $html;
  4099. }
  4100. /**
  4101. * @param string $filePath
  4102. * @param string $path
  4103. * @param array $courseInfo
  4104. * @param int $sessionId
  4105. * @param string $whatIfFileExists overwrite|rename
  4106. * @param int $userId
  4107. * @param int $groupId
  4108. * @param int $toUserId
  4109. * @param string $comment
  4110. * @return bool|path
  4111. */
  4112. public static function addFileToDocumentTool(
  4113. $filePath,
  4114. $path,
  4115. $courseInfo,
  4116. $sessionId,
  4117. $userId,
  4118. $whatIfFileExists = 'overwrite',
  4119. $groupId = null,
  4120. $toUserId = null,
  4121. $comment = null
  4122. ) {
  4123. if (!file_exists($filePath)) {
  4124. return false;
  4125. }
  4126. $fileInfo = pathinfo($filePath);
  4127. $file = array(
  4128. 'name' => $fileInfo['basename'],
  4129. 'tmp_name' => $filePath,
  4130. 'size' => filesize($filePath),
  4131. 'from_file' => true
  4132. );
  4133. $course_dir = $courseInfo['path'].'/document';
  4134. $baseWorkDir = api_get_path(SYS_COURSE_PATH).$course_dir;
  4135. $filePath = handle_uploaded_document(
  4136. $courseInfo,
  4137. $file,
  4138. $baseWorkDir,
  4139. $path,
  4140. $userId,
  4141. $groupId,
  4142. $toUserId,
  4143. false,
  4144. $whatIfFileExists,
  4145. false,
  4146. false,
  4147. $comment,
  4148. $sessionId
  4149. );
  4150. if ($filePath) {
  4151. return self::get_document_id(
  4152. $courseInfo,
  4153. $filePath,
  4154. $sessionId
  4155. );
  4156. }
  4157. return false;
  4158. }
  4159. /**
  4160. * Converts wav to mp3 file.
  4161. * Requires the ffmpeg lib. In ubuntu: sudo apt-get install ffmpeg
  4162. * @param string $wavFile
  4163. * @param bool $removeWavFileIfSuccess
  4164. * @return bool
  4165. */
  4166. public static function convertWavToMp3($wavFile, $removeWavFileIfSuccess = false)
  4167. {
  4168. if (file_exists($wavFile)) {
  4169. try {
  4170. $ffmpeg = \FFMpeg\FFMpeg::create();
  4171. $video = $ffmpeg->open($wavFile);
  4172. $mp3File = str_replace('wav', 'mp3', $wavFile);
  4173. $result = $video->save(new FFMpeg\Format\Audio\Mp3(), $mp3File);
  4174. if ($result && $removeWavFileIfSuccess) {
  4175. unlink($wavFile);
  4176. }
  4177. if (file_exists($mp3File)) {
  4178. return $mp3File;
  4179. }
  4180. } catch (Exception $e) {
  4181. error_log($e->getMessage());
  4182. error_log($e->getPrevious()->getMessage());
  4183. }
  4184. }
  4185. return false;
  4186. }
  4187. /**
  4188. * @param string $documentData wav document information
  4189. * @param array $courseInfo
  4190. * @param int $sessionId
  4191. * @param int $userId user that adds the document
  4192. * @param string $whatIfFileExists
  4193. * @param bool $deleteWavFile
  4194. *
  4195. * @return bool
  4196. */
  4197. public static function addAndConvertWavToMp3(
  4198. $documentData,
  4199. $courseInfo,
  4200. $sessionId,
  4201. $userId,
  4202. $whatIfFileExists = 'overwrite',
  4203. $deleteWavFile = false
  4204. ) {
  4205. if (empty($documentData)) {
  4206. return false;
  4207. }
  4208. if (isset($documentData['absolute_path']) &&
  4209. file_exists($documentData['absolute_path'])
  4210. ) {
  4211. $mp3FilePath = self::convertWavToMp3($documentData['absolute_path']);
  4212. error_log($mp3FilePath);
  4213. if (!empty($mp3FilePath) && file_exists($mp3FilePath)) {
  4214. $documentId = self::addFileToDocumentTool(
  4215. $mp3FilePath,
  4216. dirname($documentData['path']),
  4217. $courseInfo,
  4218. $sessionId,
  4219. $userId,
  4220. $whatIfFileExists,
  4221. null,
  4222. null,
  4223. $documentData['comment']
  4224. );
  4225. if (!empty($documentId)) {
  4226. if ($deleteWavFile) {
  4227. $coursePath = $courseInfo['directory'].'/document';
  4228. $documentPath = api_get_path(SYS_COURSE_PATH).$coursePath;
  4229. self::delete_document(
  4230. $courseInfo,
  4231. null,
  4232. $documentPath,
  4233. $sessionId,
  4234. $documentData['id']
  4235. );
  4236. }
  4237. return $documentId;
  4238. }
  4239. }
  4240. }
  4241. return false;
  4242. }
  4243. /**
  4244. * Sets
  4245. * @param string $file ($document_data['path'])
  4246. * @param string $file_url_sys
  4247. * @return string
  4248. */
  4249. public static function generateAudioTempFile($file, $file_url_sys)
  4250. {
  4251. //make temp audio
  4252. $temp_folder = api_get_path(SYS_ARCHIVE_PATH).'temp/audio';
  4253. if (!file_exists($temp_folder)) {
  4254. @mkdir($temp_folder, api_get_permissions_for_new_directories(), true);
  4255. }
  4256. //make htaccess with allow from all, and file index.html into temp/audio
  4257. $htaccess = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess';
  4258. if (!file_exists($htaccess)) {
  4259. $htaccess_content = "order deny,allow\r\nallow from all\r\nOptions -Indexes";
  4260. $fp = @ fopen(api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess', 'w');
  4261. if ($fp) {
  4262. fwrite($fp, $htaccess_content);
  4263. fclose($fp);
  4264. }
  4265. }
  4266. //encript temp name file
  4267. $name_crip = sha1(uniqid()); //encript
  4268. $findext = explode(".", $file);
  4269. $extension = $findext[count($findext) - 1];
  4270. $file_crip = $name_crip.'.'.$extension;
  4271. //copy file to temp/audio directory
  4272. $from_sys = $file_url_sys;
  4273. $to_sys = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/'.$file_crip;
  4274. if (file_exists($from_sys)) {
  4275. copy($from_sys, $to_sys);
  4276. }
  4277. //get file from tmp directory
  4278. $_SESSION['temp_audio_nanogong'] = $to_sys;
  4279. return api_get_path(WEB_ARCHIVE_PATH).'temp/audio/'.$file_crip;
  4280. }
  4281. /**
  4282. * Erase temp nanogong audio.
  4283. */
  4284. public static function removeGeneratedAudioTempFile()
  4285. {
  4286. if (isset($_SESSION['temp_audio_nanogong'])
  4287. && !empty($_SESSION['temp_audio_nanogong'])
  4288. && is_file($_SESSION['temp_audio_nanogong'])) {
  4289. unlink($_SESSION['temp_audio_nanogong']);
  4290. unset($_SESSION['temp_audio_nanogong']);
  4291. }
  4292. }
  4293. /**
  4294. * Check if the past is used in this course.
  4295. * @param array $courseInfo
  4296. * @param string $path
  4297. *
  4298. * @return array
  4299. */
  4300. public static function getDocumentByPathInCourse($courseInfo, $path)
  4301. {
  4302. $table = Database::get_course_table(TABLE_DOCUMENT);
  4303. $path = Database::escape_string($path);
  4304. $courseId = $courseInfo['real_id'];
  4305. if (empty($courseId)) {
  4306. return false;
  4307. }
  4308. $sql = "SELECT * FROM $table WHERE c_id = $courseId AND path = '$path'";
  4309. $result = Database::query($sql);
  4310. return Database::store_result($result, 'ASSOC');
  4311. }
  4312. /**
  4313. * @param array $_course
  4314. * @return int
  4315. */
  4316. public static function createDefaultAudioFolder($_course)
  4317. {
  4318. if (!isset($_course['path'])) {
  4319. return false;
  4320. }
  4321. $audioId = null;
  4322. $path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document/';
  4323. if (!is_dir($path.'audio')) {
  4324. mkdir($path.'audio', api_get_permissions_for_new_directories());
  4325. $audioId = add_document($_course, '/audio', 'folder', 0, 'Audio');
  4326. api_item_property_update(
  4327. $_course,
  4328. TOOL_DOCUMENT,
  4329. $audioId,
  4330. 'FolderCreated',
  4331. api_get_user_id(),
  4332. null,
  4333. null,
  4334. null,
  4335. null,
  4336. api_get_session_id()
  4337. );
  4338. }
  4339. return $audioId;
  4340. }
  4341. /**
  4342. * Generate a default certificate for a courses
  4343. *
  4344. * @global string $css CSS directory
  4345. * @global string $img_dir image directory
  4346. * @global string $default_course_dir Course directory
  4347. * @global string $js JS directory
  4348. * @param array $courseData The course info
  4349. * @param bool $fromBaseCourse
  4350. * @param int $sessionId
  4351. */
  4352. public static function generateDefaultCertificate($courseData, $fromBaseCourse = false, $sessionId = 0)
  4353. {
  4354. if (empty($courseData)) {
  4355. return false;
  4356. }
  4357. global $css, $img_dir, $default_course_dir, $js;
  4358. $codePath = api_get_path(REL_CODE_PATH);
  4359. $dir = '/certificates';
  4360. $comment = null;
  4361. $title = get_lang('DefaultCertificate');
  4362. $fileName = api_replace_dangerous_char($title);
  4363. $filePath = api_get_path(SYS_COURSE_PATH)."{$courseData['directory']}/document$dir";
  4364. if (!is_dir($filePath)) {
  4365. mkdir($filePath, api_get_permissions_for_new_directories());
  4366. }
  4367. $fileFullPath = "$filePath/$fileName.html";
  4368. $fileType = 'file';
  4369. $templateContent = file_get_contents(api_get_path(SYS_CODE_PATH).'gradebook/certificate_template/template.html');
  4370. $search = array('{CSS}', '{IMG_DIR}', '{REL_CODE_PATH}', '{COURSE_DIR}');
  4371. $replace = array($css.$js, $img_dir, $codePath, $default_course_dir);
  4372. $fileContent = str_replace($search, $replace, $templateContent);
  4373. $saveFilePath = "$dir/$fileName.html";
  4374. if ($fromBaseCourse) {
  4375. $defaultCertificateId = self::get_default_certificate_id(
  4376. $courseData['code'],
  4377. 0
  4378. );
  4379. if (!empty($defaultCertificateId)) {
  4380. // We have a certificate from the course base
  4381. $documentData = self::get_document_data_by_id(
  4382. $defaultCertificateId,
  4383. $courseData['code'],
  4384. false,
  4385. 0
  4386. );
  4387. if ($documentData) {
  4388. $fileContent = file_get_contents($documentData['absolute_path']);
  4389. }
  4390. }
  4391. }
  4392. if (file_exists($fileFullPath) === false) {
  4393. $result = file_put_contents($fileFullPath, $fileContent);
  4394. if ($result) {
  4395. $fileSize = filesize($fileFullPath);
  4396. $documentId = add_document(
  4397. $courseData,
  4398. $saveFilePath,
  4399. $fileType,
  4400. $fileSize,
  4401. $title,
  4402. $comment,
  4403. 0, //$readonly = 0,
  4404. true, //$save_visibility = true,
  4405. null, //$group_id = null,
  4406. $sessionId
  4407. );
  4408. api_item_property_update(
  4409. $courseData,
  4410. TOOL_DOCUMENT,
  4411. $documentId,
  4412. 'DocumentAdded',
  4413. api_get_user_id(),
  4414. null,
  4415. null,
  4416. null,
  4417. null,
  4418. $sessionId
  4419. );
  4420. $defaultCertificateId = self::get_default_certificate_id(
  4421. $courseData['code'],
  4422. $sessionId
  4423. );
  4424. if (!isset($defaultCertificateId)) {
  4425. self::attach_gradebook_certificate(
  4426. $courseData['code'],
  4427. $documentId,
  4428. $sessionId
  4429. );
  4430. }
  4431. }
  4432. }
  4433. }
  4434. /**
  4435. * Update the document name
  4436. * @param int $documentId The document id
  4437. * @param string $newName The new name
  4438. */
  4439. public static function renameDocument($documentId, $newName)
  4440. {
  4441. $documentId = intval($documentId);
  4442. $newName = Database::escape_string($newName);
  4443. $docuentTable = Database::get_course_table(TABLE_DOCUMENT);
  4444. $values = array(
  4445. 'title' => $newName
  4446. );
  4447. $whereConditions = array(
  4448. 'id = ?' => $documentId
  4449. );
  4450. Database::update($docuentTable, $values, $whereConditions);
  4451. }
  4452. /**
  4453. * Get folder/file suffix
  4454. *
  4455. * @param array $courseInfo
  4456. * @param int $sessionId
  4457. * @param int $groupId
  4458. *
  4459. * @return string
  4460. */
  4461. public static function getDocumentSuffix($courseInfo, $sessionId, $groupId)
  4462. {
  4463. // If no session or group, then no suffix.
  4464. if (empty($sessionId) && empty($groupId)) {
  4465. return '';
  4466. }
  4467. return '__'.intval($sessionId).'__'.intval($groupId);
  4468. }
  4469. /**
  4470. * Fix a document name adding session id and group id
  4471. * Turns picture.jpg -> picture__1__2.jpg
  4472. * Where 1 = session id and 2 group id
  4473. * Of session id and group id are empty then the function returns:
  4474. * picture.jpg -> picture.jpg
  4475. *
  4476. * @param string $name folder or file name
  4477. * @param string $type 'folder' or 'file'
  4478. * @param array $courseInfo
  4479. * @param int $sessionId
  4480. * @param int $groupId
  4481. *
  4482. * @return string
  4483. */
  4484. public static function fixDocumentName($name, $type, $courseInfo, $sessionId, $groupId)
  4485. {
  4486. $suffix = self::getDocumentSuffix($courseInfo, $sessionId, $groupId);
  4487. switch ($type) {
  4488. case 'folder':
  4489. $name = $name.$suffix;
  4490. break;
  4491. case 'file':
  4492. $name = self::addSuffixToFileName($name, $suffix);
  4493. break;
  4494. }
  4495. return $name;
  4496. }
  4497. /**
  4498. * Add a suffix to a file Example:
  4499. * /folder/picture.jpg => to /folder/picture_this.jpg
  4500. * where "_this" is the suffix
  4501. * @param string $name
  4502. * @param string $suffix
  4503. * @return string
  4504. */
  4505. public static function addSuffixToFileName($name, $suffix)
  4506. {
  4507. $extension = pathinfo($name, PATHINFO_EXTENSION);
  4508. $fileName = pathinfo($name, PATHINFO_FILENAME);
  4509. $dir = pathinfo($name, PATHINFO_DIRNAME);
  4510. if ($dir == '.') {
  4511. $dir = null;
  4512. }
  4513. if (!empty($dir) && $dir != '/') {
  4514. $dir = $dir.'/';
  4515. }
  4516. $name = $dir.$fileName.$suffix.'.'.$extension;
  4517. return $name;
  4518. }
  4519. /**
  4520. * Check if folder exist in the course base or in the session course
  4521. * @param string $folder Example: /folder/folder2
  4522. * @param array $courseInfo
  4523. * @param int $sessionId
  4524. * @param int $groupId group.id
  4525. *
  4526. * @return bool
  4527. */
  4528. public static function folderExists(
  4529. $folder,
  4530. $courseInfo,
  4531. $sessionId,
  4532. $groupId
  4533. ) {
  4534. $courseId = $courseInfo['real_id'];
  4535. if (empty($courseId)) {
  4536. return false;
  4537. }
  4538. $sessionId = intval($sessionId);
  4539. $folderWithSuffix = self::fixDocumentName(
  4540. $folder,
  4541. 'folder',
  4542. $courseInfo,
  4543. $sessionId,
  4544. $groupId
  4545. );
  4546. $folder = Database::escape_string($folder);
  4547. $folderWithSuffix = Database::escape_string($folderWithSuffix);
  4548. // Check if pathname already exists inside document table
  4549. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  4550. $sql = "SELECT id, path FROM $tbl_document
  4551. WHERE
  4552. filetype = 'folder' AND
  4553. c_id = $courseId AND
  4554. (path = '$folder' OR path = '$folderWithSuffix') AND
  4555. (session_id = 0 OR session_id = $sessionId)
  4556. ";
  4557. $rs = Database::query($sql);
  4558. if (Database::num_rows($rs)) {
  4559. return true;
  4560. }
  4561. return false;
  4562. }
  4563. /**
  4564. * Check if file exist in the course base or in the session course
  4565. * @param string $fileName Example: /folder/picture.jpg
  4566. * @param array $courseInfo
  4567. * @param int $sessionId
  4568. * @param int $groupId
  4569. *
  4570. * @return bool
  4571. */
  4572. public static function documentExists(
  4573. $fileName,
  4574. $courseInfo,
  4575. $sessionId,
  4576. $groupId
  4577. ) {
  4578. $courseId = $courseInfo['real_id'];
  4579. if (empty($courseId)) {
  4580. return false;
  4581. }
  4582. $sessionId = intval($sessionId);
  4583. $fileNameEscape = Database::escape_string($fileName);
  4584. $fileNameWithSuffix = self::fixDocumentName(
  4585. $fileName,
  4586. 'file',
  4587. $courseInfo,
  4588. $sessionId,
  4589. $groupId
  4590. );
  4591. $fileNameWithSuffix = Database::escape_string($fileNameWithSuffix);
  4592. // Check if pathname already exists inside document table
  4593. $table = Database::get_course_table(TABLE_DOCUMENT);
  4594. $sql = "SELECT id, path FROM $table
  4595. WHERE
  4596. filetype = 'file' AND
  4597. c_id = $courseId AND
  4598. (
  4599. path = '".$fileNameEscape."' OR
  4600. path = '$fileNameWithSuffix'
  4601. ) AND
  4602. (session_id = 0 OR session_id = $sessionId)
  4603. ";
  4604. $rs = Database::query($sql);
  4605. if (Database::num_rows($rs)) {
  4606. return true;
  4607. }
  4608. return false;
  4609. }
  4610. /**
  4611. * Undo the suffix applied to a file example:
  4612. * turns picture__1__1.jpg to picture.jpg
  4613. * @param string $name
  4614. * @param int $courseId
  4615. * @param int $sessionId
  4616. * @param int $groupId
  4617. *
  4618. * @return string
  4619. */
  4620. public static function undoFixDocumentName(
  4621. $name,
  4622. $courseId,
  4623. $sessionId,
  4624. $groupId
  4625. ) {
  4626. if (empty($sessionId) && empty($groupId)) {
  4627. return $name;
  4628. }
  4629. $suffix = self::getDocumentSuffix(
  4630. array('real_id' => $courseId),
  4631. $sessionId,
  4632. $groupId
  4633. );
  4634. $name = str_replace($suffix, '', $name);
  4635. return $name;
  4636. }
  4637. /**
  4638. * @param string $path
  4639. * @param string $name
  4640. * @param array $courseInfo
  4641. * @param int $sessionId
  4642. * @param int $groupId
  4643. *
  4644. * @return string
  4645. */
  4646. public static function getUniqueFileName($path, $name, $courseInfo, $sessionId, $groupId)
  4647. {
  4648. $counter = 1;
  4649. $filePath = $path.$name;
  4650. $uniqueName = $name;
  4651. while ($documentExists = self::documentExists(
  4652. $filePath,
  4653. $courseInfo,
  4654. $sessionId,
  4655. $groupId
  4656. )) {
  4657. $uniqueName = self::addSuffixToFileName($name, '_'.$counter);
  4658. $filePath = $path.$uniqueName;
  4659. $counter++;
  4660. }
  4661. return $uniqueName;
  4662. }
  4663. /**
  4664. * Builds the form that enables the user to
  4665. * select a directory to browse/upload in
  4666. *
  4667. * @param array An array containing the folders we want to be able to select
  4668. * @param string The current folder (path inside of the "document" directory, including the prefix "/")
  4669. * @param string Group directory, if empty, prevents documents to be uploaded (because group documents cannot be uploaded in root)
  4670. * @param boolean Whether to change the renderer (this will add a template <span> to the QuickForm object displaying the form)
  4671. * @return string html form
  4672. */
  4673. public static function build_directory_selector(
  4674. $folders,
  4675. $document_id,
  4676. $group_dir = '',
  4677. $change_renderer = false,
  4678. & $form = null,
  4679. $selectName = 'id'
  4680. ) {
  4681. $doc_table = Database::get_course_table(TABLE_DOCUMENT);
  4682. $course_id = api_get_course_int_id();
  4683. $folder_titles = array();
  4684. if (is_array($folders)) {
  4685. $escaped_folders = array();
  4686. foreach ($folders as $key => & $val) {
  4687. $escaped_folders[$key] = Database::escape_string($val);
  4688. }
  4689. $folder_sql = implode("','", $escaped_folders);
  4690. $sql = "SELECT path, title
  4691. FROM $doc_table
  4692. WHERE
  4693. filetype = 'folder' AND
  4694. c_id = $course_id AND
  4695. path IN ('".$folder_sql."')";
  4696. $res = Database::query($sql);
  4697. $folder_titles = array();
  4698. while ($obj = Database::fetch_object($res)) {
  4699. $folder_titles[$obj->path] = $obj->title;
  4700. }
  4701. }
  4702. $attributes = [];
  4703. if (empty($form)) {
  4704. $form = new FormValidator('selector', 'GET', api_get_self().'?'.api_get_cidreq());
  4705. $attributes = array('onchange' => 'javascript: document.selector.submit();');
  4706. }
  4707. $form->addElement('hidden', 'cidReq', api_get_course_id());
  4708. $parent_select = $form->addSelect(
  4709. $selectName,
  4710. get_lang('CurrentDirectory'),
  4711. '',
  4712. $attributes
  4713. );
  4714. // Group documents cannot be uploaded in the root
  4715. if (empty($group_dir)) {
  4716. $parent_select->addOption(get_lang('Documents'), '/');
  4717. if (is_array($folders)) {
  4718. foreach ($folders as $folder_id => & $folder) {
  4719. $selected = ($document_id == $folder_id) ? ' selected="selected"' : '';
  4720. $path_parts = explode('/', $folder);
  4721. $folder_titles[$folder] = cut($folder_titles[$folder], 80);
  4722. $counter = count($path_parts) - 2;
  4723. if ($counter > 0) {
  4724. $label = str_repeat('&nbsp;&nbsp;&nbsp;', $counter).' &mdash; '.$folder_titles[$folder];
  4725. } else {
  4726. $label = ' &mdash; '.$folder_titles[$folder];
  4727. }
  4728. $parent_select->addOption($label, $folder_id);
  4729. if ($selected != '') {
  4730. $parent_select->setSelected($folder_id);
  4731. }
  4732. }
  4733. }
  4734. } else {
  4735. if (!empty($folders)) {
  4736. foreach ($folders as $folder_id => & $folder) {
  4737. $selected = ($document_id == $folder_id) ? ' selected="selected"' : '';
  4738. $label = $folder_titles[$folder];
  4739. if ($folder == $group_dir) {
  4740. $label = get_lang('Documents');
  4741. } else {
  4742. $path_parts = explode('/', str_replace($group_dir, '', $folder));
  4743. $label = cut($label, 80);
  4744. $label = str_repeat('&nbsp;&nbsp;&nbsp;', count($path_parts) - 2).' &mdash; '.$label;
  4745. }
  4746. $parent_select->addOption($label, $folder_id);
  4747. if ($selected != '') {
  4748. $parent_select->setSelected($folder_id);
  4749. }
  4750. }
  4751. }
  4752. }
  4753. $html = $form->toHtml();
  4754. return $html;
  4755. }
  4756. /**
  4757. * Create a html hyperlink depending on if it's a folder or a file
  4758. *
  4759. * @param array $document_data
  4760. * @param array $course_info
  4761. * @param int $show_as_icon - if it is true, only a clickable icon will be shown
  4762. * @param int $visibility (1/0)
  4763. * @param int $counter
  4764. * @param int $size
  4765. * @param bool $isAllowedToEdit
  4766. *
  4767. * @return string url
  4768. */
  4769. public static function create_document_link(
  4770. $document_data,
  4771. $course_info,
  4772. $show_as_icon = false,
  4773. $counter = null,
  4774. $visibility,
  4775. $size = 0,
  4776. $isAllowedToEdit = false
  4777. ) {
  4778. global $dbl_click_id;
  4779. $current_session_id = api_get_session_id();
  4780. $courseParams = api_get_cidreq();
  4781. $www = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/document';
  4782. $webODFList = self::get_web_odf_extension_list();
  4783. // Get the title or the basename depending on what we're using
  4784. if ($document_data['title'] != '') {
  4785. $title = $document_data['title'];
  4786. } else {
  4787. $title = basename($document_data['path']);
  4788. }
  4789. $filetype = $document_data['filetype'];
  4790. $path = $document_data['path'];
  4791. $url_path = urlencode($document_data['path']);
  4792. // Add class="invisible" on invisible files
  4793. $visibility_class = $visibility == false ? ' class="muted"' : '';
  4794. $forcedownload_link = null;
  4795. $forcedownload_icon = null;
  4796. $prevent_multiple_click = null;
  4797. if (!$show_as_icon) {
  4798. // Build download link (icon)
  4799. $forcedownload_link = ($filetype == 'folder') ? api_get_self().'?'.$courseParams.'&action=downloadfolder&id='.$document_data['id'] : api_get_self().'?'.$courseParams.'&amp;action=download&amp;id='.$document_data['id'];
  4800. // Folder download or file download?
  4801. $forcedownload_icon = ($filetype == 'folder') ? 'save_pack.png' : 'save.png';
  4802. // Prevent multiple clicks on zipped folder download
  4803. $prevent_multiple_click = ($filetype == 'folder') ? " onclick=\"javascript: if(typeof clic_$dbl_click_id == 'undefined' || !clic_$dbl_click_id) { clic_$dbl_click_id=true; window.setTimeout('clic_".($dbl_click_id++)."=false;',10000); } else { return false; }\"" : '';
  4804. }
  4805. $target = '_self';
  4806. $is_browser_viewable_file = false;
  4807. if ($filetype == 'file') {
  4808. // Check the extension
  4809. $ext = explode('.', $path);
  4810. $ext = strtolower($ext[sizeof($ext) - 1]);
  4811. // HTML-files an some other types are shown in a frameset by default.
  4812. $is_browser_viewable_file = self::is_browser_viewable($ext);
  4813. if ($is_browser_viewable_file) {
  4814. if ($ext == 'pdf' || in_array($ext, $webODFList)) {
  4815. $url = api_get_self().'?'.$courseParams.'&amp;action=download&amp;id='.$document_data['id'];
  4816. } else {
  4817. $url = 'showinframes.php?'.$courseParams.'&id='.$document_data['id'];
  4818. }
  4819. } else {
  4820. // url-encode for problematic characters (we may not call them dangerous characters...)
  4821. $path = str_replace('%2F', '/', $url_path).'?'.$courseParams;
  4822. $url = $www.$path;
  4823. }
  4824. } else {
  4825. $url = api_get_self().'?'.$courseParams.'&id='.$document_data['id'];
  4826. }
  4827. // The little download icon
  4828. $tooltip_title = $title;
  4829. $tooltip_title_alt = $tooltip_title;
  4830. if ($path == '/shared_folder') {
  4831. $tooltip_title_alt = get_lang('UserFolders');
  4832. } elseif (strstr($path, 'shared_folder_session_')) {
  4833. $tooltip_title_alt = get_lang('UserFolders').' ('.api_get_session_name(api_get_session_id()).')';
  4834. } elseif (strstr($tooltip_title, 'sf_user_')) {
  4835. $userinfo = api_get_user_info(substr($tooltip_title, 8));
  4836. $tooltip_title_alt = get_lang('UserFolder').' '.$userinfo['complete_name'];
  4837. } elseif ($path == '/chat_files') {
  4838. $tooltip_title_alt = get_lang('ChatFiles');
  4839. } elseif ($path == '/learning_path') {
  4840. $tooltip_title_alt = get_lang('LearningPaths');
  4841. } elseif ($path == '/video') {
  4842. $tooltip_title_alt = get_lang('Video');
  4843. } elseif ($path == '/audio') {
  4844. $tooltip_title_alt = get_lang('Audio');
  4845. } elseif ($path == '/flash') {
  4846. $tooltip_title_alt = get_lang('Flash');
  4847. } elseif ($path == '/images') {
  4848. $tooltip_title_alt = get_lang('Images');
  4849. } elseif ($path == '/images/gallery') {
  4850. $tooltip_title_alt = get_lang('DefaultCourseImages');
  4851. }
  4852. $copy_to_myfiles = $open_in_new_window_link = null;
  4853. $curdirpath = isset($_GET['curdirpath']) ? Security::remove_XSS($_GET['curdirpath']) : null;
  4854. $send_to = null;
  4855. $checkExtension = $path;
  4856. if (!$show_as_icon) {
  4857. if ($filetype == 'folder') {
  4858. if ($isAllowedToEdit ||
  4859. api_is_platform_admin() ||
  4860. api_get_setting('students_download_folders') == 'true'
  4861. ) {
  4862. //filter: when I am into a shared folder, I can only show "my shared folder" for donwload
  4863. if (self::is_shared_folder($curdirpath, $current_session_id)) {
  4864. if (preg_match('/shared_folder\/sf_user_'.api_get_user_id().'$/', urldecode($forcedownload_link)) ||
  4865. preg_match('/shared_folder_session_'.$current_session_id.'\/sf_user_'.api_get_user_id().'$/', urldecode($forcedownload_link)) ||
  4866. $isAllowedToEdit || api_is_platform_admin()
  4867. ) {
  4868. $force_download_html = ($size == 0) ? '' : '<a href="'.$forcedownload_link.'" style="float:right"'.$prevent_multiple_click.'>'.
  4869. Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL).'</a>';
  4870. }
  4871. } elseif (!preg_match('/shared_folder/', urldecode($forcedownload_link)) ||
  4872. $isAllowedToEdit ||
  4873. api_is_platform_admin()
  4874. ) {
  4875. $force_download_html = ($size == 0) ? '' : '<a href="'.$forcedownload_link.'" style="float:right"'.$prevent_multiple_click.'>'.
  4876. Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL).'</a>';
  4877. }
  4878. }
  4879. } else {
  4880. $force_download_html = ($size == 0) ? '' : '<a href="'.$forcedownload_link.'" style="float:right"'.$prevent_multiple_click.' download="'.$document_data['basename'].'">'.
  4881. Display::return_icon($forcedownload_icon, get_lang('Download'), array(), ICON_SIZE_SMALL).'</a>';
  4882. }
  4883. // Copy files to user's myfiles
  4884. if (api_get_setting('allow_my_files') === 'true' &&
  4885. api_get_setting('users_copy_files') === 'true'
  4886. ) {
  4887. $copy_myfiles_link = ($filetype == 'file') ? api_get_self().'?'.$courseParams.'&action=copytomyfiles&id='.$document_data['id'] : api_get_self().'?'.$courseParams;
  4888. if ($filetype == 'file') {
  4889. $copy_to_myfiles = '<a href="'.$copy_myfiles_link.'" style="float:right"'.$prevent_multiple_click.'>'.
  4890. Display::return_icon('briefcase.png', get_lang('CopyToMyFiles'), array(), ICON_SIZE_SMALL).'&nbsp;&nbsp;</a>';
  4891. if (api_get_setting('allow_my_files') === 'false') {
  4892. $copy_to_myfiles = '';
  4893. }
  4894. }
  4895. if ($filetype == 'file') {
  4896. //$send_to = Portfolio::share('document', $document_data['id'], array('style' => 'float:right;'));
  4897. }
  4898. }
  4899. $pdf_icon = '';
  4900. $extension = pathinfo($path, PATHINFO_EXTENSION);
  4901. if (!$isAllowedToEdit &&
  4902. api_get_setting('students_export2pdf') == 'true' &&
  4903. $filetype == 'file' &&
  4904. in_array($extension, array('html', 'htm'))
  4905. ) {
  4906. $pdf_icon = ' <a style="float:right".'.$prevent_multiple_click.' href="'.api_get_self().'?'.$courseParams.'&action=export_to_pdf&id='.$document_data['id'].'&curdirpath='.$curdirpath.'">'.
  4907. Display::return_icon('pdf.png', get_lang('Export2PDF'), array(), ICON_SIZE_SMALL).'</a> ';
  4908. }
  4909. if ($is_browser_viewable_file) {
  4910. $open_in_new_window_link = '<a href="'.$www.str_replace('%2F', '/', $url_path).'?'.$courseParams.'" style="float:right"'.$prevent_multiple_click.' target="_blank">'.
  4911. Display::return_icon('open_in_new_window.png', get_lang('OpenInANewWindow'), array(), ICON_SIZE_SMALL).'&nbsp;&nbsp;</a>';
  4912. }
  4913. if ($filetype == 'file') {
  4914. // Sound preview with jplayer
  4915. if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
  4916. (preg_match('/wav$/i', urldecode($checkExtension))) ||
  4917. preg_match('/ogg$/i', urldecode($checkExtension))
  4918. ) {
  4919. return '<span style="float:left" '.$visibility_class.'>'.
  4920. $title.
  4921. '</span>'.$force_download_html.$send_to.$copy_to_myfiles.$open_in_new_window_link.$pdf_icon;
  4922. } elseif (
  4923. // Show preview
  4924. preg_match('/swf$/i', urldecode($checkExtension)) ||
  4925. preg_match('/png$/i', urldecode($checkExtension)) ||
  4926. preg_match('/gif$/i', urldecode($checkExtension)) ||
  4927. preg_match('/jpg$/i', urldecode($checkExtension)) ||
  4928. preg_match('/jpeg$/i', urldecode($checkExtension)) ||
  4929. preg_match('/bmp$/i', urldecode($checkExtension)) ||
  4930. preg_match('/svg$/i', urldecode($checkExtension))
  4931. ) {
  4932. // Simpler version of showinframesmin.php with no headers
  4933. $url = 'show_content.php?'.$courseParams.'&id='.$document_data['id'];
  4934. $class = 'ajax';
  4935. if ($visibility == false) {
  4936. $class = "ajax text-muted";
  4937. }
  4938. return Display::url(
  4939. $title,
  4940. $url,
  4941. [
  4942. 'class' => $class,
  4943. 'title' => $tooltip_title_alt,
  4944. 'data-title' => $title,
  4945. 'style' => 'float:left;'
  4946. ]
  4947. )
  4948. . $force_download_html.$send_to.$copy_to_myfiles
  4949. . $open_in_new_window_link.$pdf_icon;
  4950. } else {
  4951. // For a "PDF Download" of the file.
  4952. $pdfPreview = null;
  4953. if ($ext != 'pdf' && !in_array($ext, $webODFList)) {
  4954. $url = 'showinframes.php?'.$courseParams.'&id='.$document_data['id'];
  4955. } else {
  4956. $pdfPreview = Display::url(
  4957. Display::return_icon('preview.gif', get_lang('Preview')),
  4958. api_get_path(WEB_CODE_PATH).'document/showinframes.php?'.$courseParams.'&id='.$document_data['id'],
  4959. array('style' => 'float:right')
  4960. );
  4961. }
  4962. // No plugin just the old and good showinframes.php page
  4963. return '<a href="'.$url.'" title="'.$tooltip_title_alt.'" style="float:left" '.$visibility_class.' >'.$title.'</a>'.
  4964. $pdfPreview.$force_download_html.$send_to.$copy_to_myfiles.$open_in_new_window_link.$pdf_icon;
  4965. }
  4966. } else {
  4967. return '<a href="'.$url.'" title="'.$tooltip_title_alt.'" '.$visibility_class.' style="float:left">'.$title.'</a>'.
  4968. $force_download_html.$send_to.$copy_to_myfiles.$open_in_new_window_link.$pdf_icon;
  4969. }
  4970. // end copy files to users myfiles
  4971. } else {
  4972. // Icon column
  4973. if (preg_match('/shared_folder/', urldecode($checkExtension)) &&
  4974. preg_match('/shared_folder$/', urldecode($checkExtension)) == false &&
  4975. preg_match('/shared_folder_session_'.$current_session_id.'$/', urldecode($url)) == false
  4976. ) {
  4977. if ($filetype == 'file') {
  4978. //Sound preview with jplayer
  4979. if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
  4980. (preg_match('/wav$/i', urldecode($checkExtension))) ||
  4981. preg_match('/ogg$/i', urldecode($checkExtension))) {
  4982. $sound_preview = self::generate_media_preview($counter);
  4983. return $sound_preview;
  4984. } elseif (
  4985. // Show preview
  4986. preg_match('/swf$/i', urldecode($checkExtension)) ||
  4987. preg_match('/png$/i', urldecode($checkExtension)) ||
  4988. preg_match('/gif$/i', urldecode($checkExtension)) ||
  4989. preg_match('/jpg$/i', urldecode($checkExtension)) ||
  4990. preg_match('/jpeg$/i', urldecode($checkExtension)) ||
  4991. preg_match('/bmp$/i', urldecode($checkExtension)) ||
  4992. preg_match('/svg$/i', urldecode($checkExtension))
  4993. ) {
  4994. $url = 'showinframes.php?'.$courseParams.'&id='.$document_data['id'];
  4995. return '<a href="'.$url.'" title="'.$tooltip_title_alt.'" '.$visibility_class.' style="float:left">'.
  4996. self::build_document_icon_tag($filetype, $path, $isAllowedToEdit).
  4997. Display::return_icon('shared.png', get_lang('ResourceShared'), array()).'</a>';
  4998. } else {
  4999. return '<a href="'.$url.'" title="'.$tooltip_title_alt.'" '.$visibility_class.' style="float:left">'.
  5000. self::build_document_icon_tag($filetype, $path, $isAllowedToEdit).
  5001. Display::return_icon('shared.png', get_lang('ResourceShared'), array()).'</a>';
  5002. }
  5003. } else {
  5004. return '<a href="'.$url.'" title="'.$tooltip_title_alt.'" target="'.$target.'"'.$visibility_class.' style="float:left">'.
  5005. self::build_document_icon_tag($filetype, $path, $isAllowedToEdit).
  5006. Display::return_icon('shared.png', get_lang('ResourceShared'), array()).'</a>';
  5007. }
  5008. } else {
  5009. if ($filetype == 'file') {
  5010. // Sound preview with jplayer
  5011. if (preg_match('/mp3$/i', urldecode($checkExtension)) ||
  5012. (preg_match('/wav$/i', urldecode($checkExtension))) ||
  5013. preg_match('/ogg$/i', urldecode($checkExtension))) {
  5014. $sound_preview = self::generate_media_preview($counter);
  5015. return $sound_preview;
  5016. } elseif (
  5017. //Show preview
  5018. preg_match('/html$/i', urldecode($checkExtension)) ||
  5019. preg_match('/htm$/i', urldecode($checkExtension)) ||
  5020. preg_match('/swf$/i', urldecode($checkExtension)) ||
  5021. preg_match('/png$/i', urldecode($checkExtension)) ||
  5022. preg_match('/gif$/i', urldecode($checkExtension)) ||
  5023. preg_match('/jpg$/i', urldecode($checkExtension)) ||
  5024. preg_match('/jpeg$/i', urldecode($checkExtension)) ||
  5025. preg_match('/bmp$/i', urldecode($checkExtension)) ||
  5026. preg_match('/svg$/i', urldecode($checkExtension))
  5027. ) {
  5028. $url = 'showinframes.php?'.$courseParams.'&id='.$document_data['id']; //without preview
  5029. return '<a href="'.$url.'" title="'.$tooltip_title_alt.'" '.$visibility_class.' style="float:left">'.
  5030. self::build_document_icon_tag($filetype, $path, $isAllowedToEdit).'</a>';
  5031. } else {
  5032. return '<a href="'.$url.'" title="'.$tooltip_title_alt.'" '.$visibility_class.' style="float:left">'.
  5033. self::build_document_icon_tag($filetype, $path, $isAllowedToEdit).'</a>';
  5034. }
  5035. } else {
  5036. return '<a href="'.$url.'" title="'.$tooltip_title_alt.'" target="'.$target.'"'.$visibility_class.' style="float:left">'.
  5037. self::build_document_icon_tag($filetype, $path, $isAllowedToEdit).'</a>';
  5038. }
  5039. }
  5040. }
  5041. }
  5042. /**
  5043. * Builds an img html tag for the file type
  5044. *
  5045. * @param string $type (file/folder)
  5046. * @param string $path
  5047. * @param bool $isAllowedToEdit
  5048. * @return string img html tag
  5049. */
  5050. public static function build_document_icon_tag($type, $path, $isAllowedToEdit = null)
  5051. {
  5052. $basename = basename($path);
  5053. $current_session_id = api_get_session_id();
  5054. if (is_null($isAllowedToEdit)) {
  5055. $isAllowedToEdit = api_is_allowed_to_edit(null, true);
  5056. }
  5057. $user_image = false;
  5058. if ($type == 'file') {
  5059. $icon = choose_image($basename);
  5060. $basename = substr(strrchr($basename, '.'), 1);
  5061. } else {
  5062. if ($path == '/shared_folder') {
  5063. $icon = 'folder_users.png';
  5064. if ($isAllowedToEdit) {
  5065. $basename = get_lang('HelpUsersFolder');
  5066. } else {
  5067. $basename = get_lang('UserFolders');
  5068. }
  5069. } elseif (strstr($basename, 'sf_user_')) {
  5070. $userInfo = api_get_user_info(substr($basename, 8));
  5071. $icon = $userInfo['avatar_small'];
  5072. $basename = get_lang('UserFolder').' '.$userInfo['complete_name'];
  5073. $user_image = true;
  5074. } elseif (strstr($path, 'shared_folder_session_')) {
  5075. $sessionName = api_get_session_name($current_session_id);
  5076. if ($isAllowedToEdit) {
  5077. $basename = '***('.$sessionName.')*** '.get_lang('HelpUsersFolder');
  5078. } else {
  5079. $basename = get_lang('UserFolders').' ('.$sessionName.')';
  5080. }
  5081. $icon = 'folder_users.png';
  5082. } else {
  5083. $icon = 'folder_document.gif';
  5084. if ($path == '/audio') {
  5085. $icon = 'folder_audio.gif';
  5086. if ($isAllowedToEdit) {
  5087. $basename = get_lang('HelpDefaultDirDocuments');
  5088. } else {
  5089. $basename = get_lang('Audio');
  5090. }
  5091. } elseif ($path == '/flash') {
  5092. $icon = 'folder_flash.gif';
  5093. if ($isAllowedToEdit) {
  5094. $basename = get_lang('HelpDefaultDirDocuments');
  5095. } else {
  5096. $basename = get_lang('Flash');
  5097. }
  5098. } elseif ($path == '/images') {
  5099. $icon = 'folder_images.gif';
  5100. if ($isAllowedToEdit) {
  5101. $basename = get_lang('HelpDefaultDirDocuments');
  5102. } else {
  5103. $basename = get_lang('Images');
  5104. }
  5105. } elseif ($path == '/video') {
  5106. $icon = 'folder_video.gif';
  5107. if ($isAllowedToEdit) {
  5108. $basename = get_lang('HelpDefaultDirDocuments');
  5109. } else {
  5110. $basename = get_lang('Video');
  5111. }
  5112. } elseif ($path == '/images/gallery') {
  5113. $icon = 'folder_gallery.gif';
  5114. if ($isAllowedToEdit) {
  5115. $basename = get_lang('HelpDefaultDirDocuments');
  5116. } else {
  5117. $basename = get_lang('Gallery');
  5118. }
  5119. } elseif ($path == '/chat_files') {
  5120. $icon = 'folder_chat.png';
  5121. if ($isAllowedToEdit) {
  5122. $basename = get_lang('HelpFolderChat');
  5123. } else {
  5124. $basename = get_lang('ChatFiles');
  5125. }
  5126. } elseif ($path == '/learning_path') {
  5127. $icon = 'folder_learningpath.gif';
  5128. if ($isAllowedToEdit) {
  5129. $basename = get_lang('HelpFolderLearningPaths');
  5130. } else {
  5131. $basename = get_lang('LearningPaths');
  5132. }
  5133. }
  5134. }
  5135. }
  5136. if ($user_image) {
  5137. return Display::img($icon, $basename, array(), false);
  5138. }
  5139. return Display::return_icon($icon, $basename, array(), ICON_SIZE_MEDIUM);
  5140. }
  5141. /**
  5142. * Creates the row of edit icons for a file/folder
  5143. *
  5144. * @param string $curdirpath current path (cfr open folder)
  5145. * @param string $type (file/folder)
  5146. * @param string $path dbase path of file/folder
  5147. * @param int $visibility (1/0)
  5148. * @param int $id dbase id of the document
  5149. * @return string html img tags with hyperlinks
  5150. */
  5151. public static function build_edit_icons($document_data, $id, $is_template, $is_read_only = 0, $visibility)
  5152. {
  5153. $sessionId = api_get_session_id();
  5154. $courseParams = api_get_cidreq();
  5155. $web_odf_extension_list = self::get_web_odf_extension_list();
  5156. $document_id = $document_data['id'];
  5157. $type = $document_data['filetype'];
  5158. $is_read_only = $document_data['readonly'];
  5159. $path = $document_data['path'];
  5160. $parent_id = self::get_document_id(
  5161. api_get_course_info(),
  5162. dirname($path),
  5163. 0
  5164. );
  5165. if (empty($parent_id) && !empty($sessionId)) {
  5166. $parent_id = self::get_document_id(
  5167. api_get_course_info(),
  5168. dirname($path),
  5169. $sessionId
  5170. );
  5171. }
  5172. $curdirpath = dirname($document_data['path']);
  5173. $is_certificate_mode = self::is_certificate_mode($path);
  5174. $curdirpath = urlencode($curdirpath);
  5175. $extension = pathinfo($path, PATHINFO_EXTENSION);
  5176. //@todo Implement remote support for converter
  5177. $usePpt2lp = (api_get_setting('service_ppt2lp', 'active') == 'true' && api_get_setting('service_ppt2lp', 'host') == 'localhost');
  5178. $formatTypeList = self::getFormatTypeListConvertor('from', $extension);
  5179. $formatType = current($formatTypeList);
  5180. // Build URL-parameters for table-sorting
  5181. $sort_params = array();
  5182. if (isset($_GET['column'])) {
  5183. $sort_params[] = 'column='.Security::remove_XSS($_GET['column']);
  5184. }
  5185. if (isset($_GET['page_nr'])) {
  5186. $sort_params[] = 'page_nr='.Security::remove_XSS($_GET['page_nr']);
  5187. }
  5188. if (isset($_GET['per_page'])) {
  5189. $sort_params[] = 'per_page='.Security::remove_XSS($_GET['per_page']);
  5190. }
  5191. if (isset($_GET['direction'])) {
  5192. $sort_params[] = 'direction='.Security::remove_XSS($_GET['direction']);
  5193. }
  5194. $sort_params = implode('&amp;', $sort_params);
  5195. $visibility_icon = ($visibility == 0) ? 'invisible' : 'visible';
  5196. $visibility_command = ($visibility == 0) ? 'set_visible' : 'set_invisible';
  5197. $modify_icons = '';
  5198. // If document is read only *or* we're in a session and the document
  5199. // is from a non-session context, hide the edition capabilities
  5200. if ($is_read_only /* or ($session_id!=api_get_session_id()) */) {
  5201. if (api_is_course_admin() || api_is_platform_admin()) {
  5202. if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
  5203. $modify_icons = '<a href="edit_draw.php?'.$courseParams.'&id='.$document_id.'">'.
  5204. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5205. } elseif (in_array($extension, $web_odf_extension_list) && api_get_setting('enabled_support_odf') === true) {
  5206. $modify_icons = '<a href="edit_odf.php?'.$courseParams.'&id='.$document_id.'">'.
  5207. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5208. } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
  5209. $modify_icons = '<a href="edit_paint.php?'.$courseParams.'&id='.$document_id.'">'.
  5210. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5211. } else {
  5212. $modify_icons = '<a href="edit_document.php?'.$courseParams.'&id='.$document_id.'">'.
  5213. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5214. }
  5215. } else {
  5216. $modify_icons = Display::return_icon('edit_na.png', get_lang('Modify'), '', ICON_SIZE_SMALL);
  5217. }
  5218. $modify_icons .= '&nbsp;'.Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL);
  5219. if (api_is_allowed_to_edit() || api_is_platform_admin()) {
  5220. $modify_icons .= '&nbsp;'.Display::return_icon($visibility_icon.'.png', get_lang('VisibilityCannotBeChanged'), '', ICON_SIZE_SMALL);
  5221. }
  5222. $modify_icons .= '&nbsp;'.Display::return_icon('delete_na.png', get_lang('Delete'), array(), ICON_SIZE_SMALL);
  5223. } else {
  5224. //Edit button
  5225. if (in_array($path, self::get_system_folders())) {
  5226. $modify_icons = Display::return_icon('edit_na.png', get_lang('Modify'), '', ICON_SIZE_SMALL);
  5227. } elseif ($is_certificate_mode) {
  5228. // gradebook category doesn't seem to be taken into account
  5229. $modify_icons = '<a href="edit_document.php?'.$courseParams.'&amp;id='.$document_id.'&curdirpath=/certificates">'.Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5230. } else {
  5231. if ($sessionId) {
  5232. if ($document_data['session_id'] == $sessionId) {
  5233. if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
  5234. $modify_icons = '<a href="edit_draw.php?'.$courseParams.'&amp;id='.$document_id.'">'.
  5235. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5236. } elseif (in_array($extension, $web_odf_extension_list) && api_get_setting('enabled_support_odf') === true) {
  5237. $modify_icons = '<a href="edit_odf.php?'.$courseParams.'&id='.$document_id.'">'.
  5238. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5239. } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
  5240. $modify_icons = '<a href="edit_paint.php?'.$courseParams.'&id='.$document_id.'">'.
  5241. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5242. } else {
  5243. $modify_icons = '<a href="edit_document.php?'.$courseParams.'&amp;id='.$document_id.'">'.
  5244. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5245. }
  5246. } else {
  5247. $modify_icons .= '&nbsp;'.Display::return_icon('edit_na.png', get_lang('Edit'), array(), ICON_SIZE_SMALL).'</a>';
  5248. }
  5249. } else {
  5250. if ($extension == 'svg' && api_browser_support('svg') && api_get_setting('enabled_support_svg') == 'true') {
  5251. $modify_icons = '<a href="edit_draw.php?'.$courseParams.'&amp;id='.$document_id.'">'.
  5252. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5253. } elseif (in_array($extension, $web_odf_extension_list) && api_get_setting('enabled_support_odf') === true) {
  5254. $modify_icons = '<a href="edit_odf.php?'.$courseParams.'&id='.$document_id.'">'.
  5255. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5256. } elseif ($extension == 'png' || $extension == 'jpg' || $extension == 'jpeg' || $extension == 'bmp' || $extension == 'gif' || $extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true') {
  5257. $modify_icons = '<a href="edit_paint.php?'.$courseParams.'&amp;id='.$document_id.'">'.
  5258. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5259. } else {
  5260. $modify_icons = '<a href="edit_document.php?'.$courseParams.'&amp;id='.$document_id.'">'.
  5261. Display::return_icon('edit.png', get_lang('Modify'), '', ICON_SIZE_SMALL).'</a>';
  5262. }
  5263. }
  5264. }
  5265. // Move button.
  5266. if ($is_certificate_mode || in_array($path, self::get_system_folders())) {
  5267. $modify_icons .= '&nbsp;'.Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL).'</a>';
  5268. } else {
  5269. if ($sessionId) {
  5270. if ($document_data['session_id'] == $sessionId) {
  5271. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&amp;id='.$parent_id.'&amp;move='.$document_id.'">'.
  5272. Display::return_icon('move.png', get_lang('Move'), array(), ICON_SIZE_SMALL).'</a>';
  5273. } else {
  5274. $modify_icons .= '&nbsp;'.Display::return_icon('move_na.png', get_lang('Move'), array(), ICON_SIZE_SMALL).'</a>';
  5275. }
  5276. } else {
  5277. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&amp;id='.$parent_id.'&amp;move='.$document_id.'">'.
  5278. Display::return_icon('move.png', get_lang('Move'), array(), ICON_SIZE_SMALL).'</a>';
  5279. }
  5280. }
  5281. //Visibility button
  5282. if ($is_certificate_mode) {
  5283. $modify_icons .= '&nbsp;'.Display::return_icon($visibility_icon.'.png', get_lang('VisibilityCannotBeChanged'), array(), ICON_SIZE_SMALL).'</a>';
  5284. } else {
  5285. if (api_is_allowed_to_edit() || api_is_platform_admin()) {
  5286. if ($visibility_icon == 'invisible') {
  5287. $tip_visibility = get_lang('Show');
  5288. } else {
  5289. $tip_visibility = get_lang('Hide');
  5290. }
  5291. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&amp;id='.$parent_id.'&amp;'.$visibility_command.'='.$id.'&amp;'.$sort_params.'">'.
  5292. Display::return_icon($visibility_icon.'.png', $tip_visibility, '', ICON_SIZE_SMALL).'</a>';
  5293. }
  5294. }
  5295. // Delete button
  5296. if (in_array($path, self::get_system_folders())) {
  5297. $modify_icons .= '&nbsp;'.Display::return_icon('delete_na.png', get_lang('ThisFolderCannotBeDeleted'), array(), ICON_SIZE_SMALL);
  5298. } else {
  5299. $titleToShow = addslashes(basename($document_data['title']));
  5300. if (isset($_GET['curdirpath']) &&
  5301. $_GET['curdirpath'] == '/certificates' &&
  5302. self::get_default_certificate_id(api_get_course_id()) == $id
  5303. ) {
  5304. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&amp;curdirpath='.$curdirpath.'&action=delete_item&id='.$parent_id.'&deleteid='.$document_id.'&amp;'.$sort_params.'delete_certificate_id='.$id.'" onclick="return confirmation(\''.$titleToShow.'\');">'.
  5305. Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL).'</a>';
  5306. } else {
  5307. if ($is_certificate_mode) {
  5308. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&amp;curdirpath='.$curdirpath.'&action=delete_item&id='.$parent_id.'&deleteid='.$document_id.'&amp;'.$sort_params.'" onclick="return confirmation(\''.$titleToShow.'\');">'.
  5309. Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL).'</a>';
  5310. } else {
  5311. if ($sessionId) {
  5312. if ($document_data['session_id'] == $sessionId) {
  5313. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&amp;curdirpath='.$curdirpath.'&action=delete_item&id='.$parent_id.'&deleteid='.$document_id.'&amp;'.$sort_params.'" onclick="return confirmation(\''.$titleToShow.'\');">'.
  5314. Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL).'</a>';
  5315. } else {
  5316. $modify_icons .= '&nbsp;'.Display::return_icon('delete_na.png', get_lang('ThisFolderCannotBeDeleted'), array(), ICON_SIZE_SMALL);
  5317. }
  5318. } else {
  5319. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&amp;curdirpath='.$curdirpath.'&action=delete_item&id='.$parent_id.'&deleteid='.$document_id.'&amp;'.$sort_params.'" onclick="return confirmation(\''.$titleToShow.'\');">'.
  5320. Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL).'</a>';
  5321. }
  5322. }
  5323. }
  5324. }
  5325. // Add action to covert to PDF, will create a new document whit same filename but .pdf extension
  5326. // @TODO: add prompt to select a format target
  5327. if (in_array($path, self::get_system_folders())) {
  5328. // nothing to do
  5329. } else {
  5330. if ($usePpt2lp && $formatType) {
  5331. $modify_icons .= '&nbsp;<a class="convertAction" href="#" '.
  5332. 'data-documentId = '.$document_id.
  5333. ' data-formatType = '.$formatType.'>'.
  5334. Display::return_icon(
  5335. 'convert.png',
  5336. get_lang('Convert'),
  5337. array(),
  5338. ICON_SIZE_SMALL
  5339. ).'</a>';
  5340. }
  5341. }
  5342. }
  5343. if ($type == 'file' && ($extension == 'html' || $extension == 'htm')) {
  5344. if ($is_template == 0) {
  5345. if ((isset($_GET['curdirpath']) && $_GET['curdirpath'] != '/certificates') || !isset($_GET['curdirpath'])) {
  5346. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&amp;curdirpath='.$curdirpath.'&amp;add_as_template='.$id.'&amp;'.$sort_params.'">'.
  5347. Display::return_icon('wizard.png', get_lang('AddAsTemplate'), array(), ICON_SIZE_SMALL).'</a>';
  5348. }
  5349. if (isset($_GET['curdirpath']) && $_GET['curdirpath'] == '/certificates') {//allow attach certificate to course
  5350. $visibility_icon_certificate = 'nocertificate';
  5351. if (self::get_default_certificate_id(api_get_course_id()) == $id) {
  5352. $visibility_icon_certificate = 'certificate';
  5353. $certificate = get_lang('DefaultCertificate');
  5354. $preview = get_lang('PreviewCertificate');
  5355. $is_preview = true;
  5356. } else {
  5357. $is_preview = false;
  5358. $certificate = get_lang('NoDefaultCertificate');
  5359. }
  5360. if (isset($_GET['selectcat'])) {
  5361. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&amp;curdirpath='.$curdirpath.'&amp;selectcat='.intval($_GET['selectcat']).'&amp;set_certificate='.$id.'&amp;'.$sort_params.'">';
  5362. $modify_icons .= Display::return_icon($visibility_icon_certificate.'.png', $certificate);
  5363. $modify_icons .= '</a>';
  5364. if ($is_preview) {
  5365. $modify_icons .= '&nbsp;<a target="_blank" href="'.api_get_self().'?'.$courseParams.'&amp;curdirpath='.$curdirpath.'&amp;set_preview='.$id.'&amp;'.$sort_params.'" >'.
  5366. Display::return_icon('preview_view.png', $preview, '', ICON_SIZE_SMALL).'</a>';
  5367. }
  5368. }
  5369. }
  5370. } else {
  5371. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&curdirpath='.$curdirpath.'&amp;remove_as_template='.$id.'&amp;'.$sort_params.'">'.
  5372. Display::return_icon('wizard_na.png', get_lang('RemoveAsTemplate'), '', ICON_SIZE_SMALL).'</a>';
  5373. }
  5374. $modify_icons .= '&nbsp;<a href="'.api_get_self().'?'.$courseParams.'&action=export_to_pdf&id='.$id.'&curdirpath='.$curdirpath.'">'.
  5375. Display::return_icon('pdf.png', get_lang('Export2PDF'), array(), ICON_SIZE_SMALL).'</a>';
  5376. }
  5377. return $modify_icons;
  5378. }
  5379. /**
  5380. * @param $folders
  5381. * @param $curdirpath
  5382. * @param $move_file
  5383. * @param string $group_dir
  5384. * @param $form
  5385. *
  5386. * @return string
  5387. */
  5388. public static function build_move_to_selector($folders, $curdirpath, $move_file, $group_dir = '')
  5389. {
  5390. $form = new FormValidator('move_to', 'post', api_get_self().'?'.api_get_cidreq());
  5391. // Form title
  5392. $form->addElement('hidden', 'move_file', $move_file);
  5393. $options = array();
  5394. // Group documents cannot be uploaded in the root
  5395. if ($group_dir == '') {
  5396. if ($curdirpath != '/') {
  5397. $options['/'] = get_lang('Documents');
  5398. }
  5399. if (is_array($folders)) {
  5400. foreach ($folders as & $folder) {
  5401. // Hide some folders
  5402. if ($folder == '/HotPotatoes_files' ||
  5403. $folder == '/certificates' ||
  5404. basename($folder) == 'css'
  5405. ) {
  5406. continue;
  5407. }
  5408. // Admin setting for Hide/Show the folders of all users
  5409. if (api_get_setting('show_users_folders') == 'false' &&
  5410. (strstr($folder, '/shared_folder') || strstr($folder, 'shared_folder_session_'))
  5411. ) {
  5412. continue;
  5413. }
  5414. // Admin setting for Hide/Show Default folders to all users
  5415. if (api_get_setting('show_default_folders') == 'false' &&
  5416. (
  5417. $folder == '/images' ||
  5418. $folder == '/flash' ||
  5419. $folder == '/audio' ||
  5420. $folder == '/video' ||
  5421. strstr($folder, '/images/gallery') ||
  5422. $folder == '/video/flv'
  5423. )
  5424. ) {
  5425. continue;
  5426. }
  5427. // Admin setting for Hide/Show chat history folder
  5428. if (api_get_setting('show_chat_folder') == 'false' &&
  5429. $folder == '/chat_files') {
  5430. continue;
  5431. }
  5432. // You cannot move a file to:
  5433. // 1. current directory
  5434. // 2. inside the folder you want to move
  5435. // 3. inside a subfolder of the folder you want to move
  5436. if (($curdirpath != $folder) &&
  5437. ($folder != $move_file) &&
  5438. (substr($folder, 0, strlen($move_file) + 1) != $move_file.'/')
  5439. ) {
  5440. $path_displayed = $folder;
  5441. // If document title is used, we have to display titles instead of real paths...
  5442. $path_displayed = self::get_titles_of_path($folder);
  5443. if (empty($path_displayed)) {
  5444. $path_displayed = get_lang('Untitled');
  5445. }
  5446. $options[$folder] = $path_displayed;
  5447. }
  5448. }
  5449. }
  5450. } else {
  5451. foreach ($folders as $folder) {
  5452. if (($curdirpath != $folder) &&
  5453. ($folder != $move_file) &&
  5454. (substr($folder, 0, strlen($move_file) + 1) != $move_file.'/')
  5455. ) {
  5456. // Cannot copy dir into his own subdir
  5457. $path_displayed = self::get_titles_of_path($folder);
  5458. $display_folder = substr($path_displayed, strlen($group_dir));
  5459. $display_folder = ($display_folder == '') ? get_lang('Documents') : $display_folder;
  5460. //$form .= '<option value="'.$folder.'">'.$display_folder.'</option>';
  5461. $options[$folder] = $display_folder;
  5462. }
  5463. }
  5464. }
  5465. $form->addElement('select', 'move_to', get_lang('MoveTo'), $options);
  5466. $form->addButtonNext(get_lang('MoveElement'), 'move_file_submit');
  5467. return $form->returnForm();
  5468. }
  5469. /**
  5470. * Gets the path translated with title of docs and folders
  5471. * @param string $path the real path
  5472. * @return the path which should be displayed
  5473. */
  5474. public static function get_titles_of_path($path)
  5475. {
  5476. global $tmp_folders_titles;
  5477. $course_id = api_get_course_int_id();
  5478. $nb_slashes = substr_count($path, '/');
  5479. $current_slash_pos = 0;
  5480. $path_displayed = '';
  5481. for ($i = 0; $i < $nb_slashes; $i++) {
  5482. // For each folder of the path, retrieve title.
  5483. $current_slash_pos = strpos($path, '/', $current_slash_pos + 1);
  5484. $tmp_path = substr($path, strpos($path, '/', 0), $current_slash_pos);
  5485. if (empty($tmp_path)) {
  5486. // If empty, then we are in the final part of the path
  5487. $tmp_path = $path;
  5488. }
  5489. if (!empty($tmp_folders_titles[$tmp_path])) {
  5490. // If this path has soon been stored here we don't need a new query
  5491. $path_displayed .= $tmp_folders_titles[$tmp_path];
  5492. } else {
  5493. $sql = 'SELECT title FROM '.Database::get_course_table(TABLE_DOCUMENT).'
  5494. WHERE c_id = ' . $course_id.' AND path LIKE BINARY "'.$tmp_path.'"';
  5495. $rs = Database::query($sql);
  5496. $tmp_title = '/'.Database::result($rs, 0, 0);
  5497. $path_displayed .= $tmp_title;
  5498. $tmp_folders_titles[$tmp_path] = $tmp_title;
  5499. }
  5500. }
  5501. return $path_displayed;
  5502. }
  5503. /**
  5504. * Creates form that asks for the directory name.
  5505. * @return string html-output text for the form
  5506. */
  5507. public static function create_dir_form($dirId)
  5508. {
  5509. global $document_id;
  5510. $form = new FormValidator('create_dir_form', 'post', api_get_self().'?'.api_get_cidreq());
  5511. $form->addElement('hidden', 'create_dir', 1);
  5512. $form->addElement('hidden', 'dir_id', intval($document_id));
  5513. $form->addElement('hidden', 'id', intval($dirId));
  5514. $form->addElement('header', get_lang('CreateDir'));
  5515. $form->addText('dirname', get_lang('NewDir'), array('autofocus' => 'autofocus'));
  5516. $form->addButtonCreate(get_lang('CreateFolder'));
  5517. return $form->returnForm();
  5518. }
  5519. /**
  5520. * Checks whether the user is in shared folder
  5521. * @return return bool Return true when user is into shared folder
  5522. */
  5523. public static function is_shared_folder($curdirpath, $current_session_id)
  5524. {
  5525. $clean_curdirpath = Security::remove_XSS($curdirpath);
  5526. if ($clean_curdirpath == '/shared_folder') {
  5527. return true;
  5528. } elseif ($clean_curdirpath == '/shared_folder_session_'.$current_session_id) {
  5529. return true;
  5530. } else {
  5531. return false;
  5532. }
  5533. }
  5534. /**
  5535. * Checks whether the user is into any user shared folder
  5536. * @return return bool Return true when user is in any user shared folder
  5537. */
  5538. public static function is_any_user_shared_folder($path, $current_session_id)
  5539. {
  5540. $clean_path = Security::remove_XSS($path);
  5541. if (strpos($clean_path, 'shared_folder/sf_user_')) {
  5542. return true;
  5543. } elseif (strpos($clean_path, 'shared_folder_session_'.$current_session_id.'/sf_user_')) {
  5544. return true;
  5545. } else {
  5546. return false;
  5547. }
  5548. }
  5549. /**
  5550. * Checks whether the user is into his shared folder or into a subfolder
  5551. * @return bool Return true when user is in his user shared folder or into a subfolder
  5552. */
  5553. public static function is_my_shared_folder($user_id, $path, $current_session_id)
  5554. {
  5555. $clean_path = Security::remove_XSS($path).'/';
  5556. //for security does not remove the last slash
  5557. $main_user_shared_folder = '/shared_folder\/sf_user_'.$user_id.'\//';
  5558. //for security does not remove the last slash
  5559. $main_user_shared_folder_session = '/shared_folder_session_'.$current_session_id.'\/sf_user_'.$user_id.'\//';
  5560. if (preg_match($main_user_shared_folder, $clean_path)) {
  5561. return true;
  5562. } elseif (preg_match($main_user_shared_folder_session, $clean_path)) {
  5563. return true;
  5564. } else {
  5565. return false;
  5566. }
  5567. }
  5568. /**
  5569. * Check if the file name or folder searched exist
  5570. * @return bool Return true when exist
  5571. */
  5572. public static function search_keyword($document_name, $keyword)
  5573. {
  5574. if (api_strripos($document_name, $keyword) !== false) {
  5575. return true;
  5576. } else {
  5577. return false;
  5578. }
  5579. }
  5580. /**
  5581. * Checks whether a document can be previewed by using the browser.
  5582. * @param string $file_extension The filename extension of the document (it must be in lower case).
  5583. * @return bool Returns TRUE or FALSE.
  5584. */
  5585. public static function is_browser_viewable($file_extension)
  5586. {
  5587. static $allowed_extensions = array(
  5588. 'htm', 'html', 'xhtml',
  5589. 'gif', 'jpg', 'jpeg', 'png', 'tif', 'tiff',
  5590. 'pdf', 'svg', 'swf',
  5591. 'txt', 'log',
  5592. 'mp4', 'ogg', 'ogv', 'ogx', 'mpg', 'mpeg', 'mov', 'avi', 'webm', 'wmv',
  5593. 'mp3', 'oga', 'wav', 'au', 'wma', 'mid', 'kar'
  5594. );
  5595. /*
  5596. //TODO: make a admin swich to strict mode
  5597. 1. global default $allowed_extensions only: 'htm', 'html', 'xhtml', 'gif', 'jpg', 'jpeg', 'png', 'bmp', 'txt', 'log'
  5598. if (in_array($file_extension, $allowed_extensions)) { // Assignment + a logical check.
  5599. return true;
  5600. }
  5601. 2. check native support
  5602. 3. check plugins: quicktime, mediaplayer, vlc, acrobat, flash, java
  5603. */
  5604. if (!($result = in_array($file_extension, $allowed_extensions))) { // Assignment + a logical check.
  5605. return false;
  5606. }
  5607. //check native support (Explorer, Opera, Firefox, Chrome, Safari)
  5608. if ($file_extension == "pdf") {
  5609. return api_browser_support('pdf');
  5610. } elseif ($file_extension == "mp3") {
  5611. return api_browser_support('mp3');
  5612. } elseif ($file_extension == "mp4") {
  5613. return api_browser_support('mp4');
  5614. } elseif ($file_extension == "ogg" || $file_extension == "ogx" || $file_extension == "ogv" || $file_extension == "oga") {
  5615. return api_browser_support('ogg');
  5616. } elseif ($file_extension == "svg") {
  5617. return api_browser_support('svg');
  5618. } elseif ($file_extension == "mpg" || $file_extension == "mpeg") {
  5619. return api_browser_support('mpg');
  5620. } elseif ($file_extension == "mov") {
  5621. return api_browser_support('mov');
  5622. } elseif ($file_extension == "wav") {
  5623. return api_browser_support('wav');
  5624. } elseif ($file_extension == "mid" || $file_extension == "kar") {
  5625. return api_browser_support('mid');
  5626. } elseif ($file_extension == "avi") {
  5627. return api_browser_support('avi');
  5628. } elseif ($file_extension == "wma") {
  5629. return api_browser_support('wma');
  5630. } elseif ($file_extension == "wmv") {
  5631. return api_browser_support('wmv');
  5632. } elseif ($file_extension == "tif" || $file_extension == "tiff") {
  5633. return api_browser_support('tif');
  5634. } elseif ($file_extension == "mov") {
  5635. return api_browser_support('mov');
  5636. } elseif ($file_extension == "au") {
  5637. return api_browser_support('au');
  5638. } elseif ($file_extension == "webm") {
  5639. return api_browser_support('webm');
  5640. }
  5641. return $result;
  5642. }
  5643. /**
  5644. * @param array $courseInfo
  5645. * @param int $sessionId
  5646. *
  5647. * @return array
  5648. */
  5649. public static function getDeletedDocuments($courseInfo, $sessionId = 0)
  5650. {
  5651. $table = Database::get_course_table(TABLE_DOCUMENT);
  5652. $courseId = $courseInfo['real_id'];
  5653. $sessionCondition = api_get_session_condition($sessionId);
  5654. $sql = "SELECT * FROM $table
  5655. WHERE
  5656. path LIKE '%DELETED%' AND
  5657. c_id = $courseId
  5658. $sessionCondition
  5659. ORDER BY path
  5660. ";
  5661. $result = Database::query($sql);
  5662. $files = array();
  5663. while ($document = Database::fetch_array($result, 'ASSOC')) {
  5664. $files[] = $document;
  5665. }
  5666. return $files;
  5667. }
  5668. /**
  5669. * @param int $id
  5670. * @param array $courseInfo
  5671. * @param int $sessionId
  5672. *
  5673. * @return array
  5674. */
  5675. public static function getDeletedDocument($id, $courseInfo, $sessionId = 0)
  5676. {
  5677. if (empty($courseInfo)) {
  5678. return false;
  5679. }
  5680. $table = Database::get_course_table(TABLE_DOCUMENT);
  5681. $courseId = $courseInfo['real_id'];
  5682. $sessionCondition = api_get_session_condition($sessionId);
  5683. $sql = "SELECT * FROM $table
  5684. WHERE
  5685. path LIKE '%DELETED%' AND
  5686. id = $id AND
  5687. c_id = $courseId
  5688. $sessionCondition
  5689. LIMIT 1
  5690. ";
  5691. $result = Database::query($sql);
  5692. if (Database::num_rows($result)) {
  5693. $result = Database::fetch_array($result, 'ASSOC');
  5694. return $result;
  5695. }
  5696. return array();
  5697. }
  5698. /**
  5699. * @param int $id
  5700. * @param array $courseInfo
  5701. * @param int $sessionId
  5702. * @return bool
  5703. */
  5704. public static function purgeDocument($id, $courseInfo, $sessionId = 0)
  5705. {
  5706. $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
  5707. if (!empty($document)) {
  5708. $path = $document['path'];
  5709. $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
  5710. my_delete($coursePath.$path);
  5711. // Hard delete.
  5712. self::deleteDocumentFromDb($id, $courseInfo, $sessionId, true);
  5713. return true;
  5714. }
  5715. return false;
  5716. }
  5717. /**
  5718. * @param array $courseInfo
  5719. * @param int $sessionId
  5720. */
  5721. public static function purgeDocuments($courseInfo, $sessionId)
  5722. {
  5723. $files = self::getDeletedDocuments($courseInfo, $sessionId);
  5724. foreach ($files as $file) {
  5725. self::purgeDocument($file['id'], $courseInfo, $sessionId);
  5726. }
  5727. }
  5728. /**
  5729. * @param int $id
  5730. * @param array $courseInfo
  5731. * @param int $sessionId
  5732. * @return bool
  5733. */
  5734. public static function downloadDeletedDocument($id, $courseInfo, $sessionId)
  5735. {
  5736. $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
  5737. if (!empty($document)) {
  5738. $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
  5739. if (Security::check_abs_path($coursePath.$document['path'], $coursePath)) {
  5740. self::file_send_for_download($coursePath.$document['path']);
  5741. exit;
  5742. }
  5743. }
  5744. }
  5745. /**
  5746. * @param array $courseInfo
  5747. * @param int $sessionId
  5748. *
  5749. * @return bool
  5750. */
  5751. public static function downloadAllDeletedDocument($courseInfo, $sessionId)
  5752. {
  5753. // Zip library for creation of the zip file.
  5754. require api_get_path(LIBRARY_PATH).'pclzip/pclzip.lib.php';
  5755. $files = self::getDeletedDocuments($courseInfo, $sessionId);
  5756. if (empty($files)) {
  5757. return false;
  5758. }
  5759. $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
  5760. // Creating a ZIP file.
  5761. $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().".zip";
  5762. $zip = new PclZip($tempZipFile);
  5763. foreach ($files as $file) {
  5764. $zip->add(
  5765. $coursePath.$file['path'],
  5766. PCLZIP_OPT_REMOVE_PATH,
  5767. $coursePath
  5768. );
  5769. }
  5770. if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
  5771. self::file_send_for_download($tempZipFile, true);
  5772. @unlink($tempZipFile);
  5773. exit;
  5774. }
  5775. }
  5776. /**
  5777. *
  5778. * Delete documents from a session in a course.
  5779. * @param array $courseInfo
  5780. * @param int $sessionId
  5781. *
  5782. * @return bool
  5783. */
  5784. public static function deleteDocumentsFromSession($courseInfo, $sessionId)
  5785. {
  5786. if (empty($courseInfo)) {
  5787. return false;
  5788. }
  5789. if (empty($sessionId)) {
  5790. return false;
  5791. }
  5792. $itemPropertyTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
  5793. $documentTable = Database::get_course_table(TABLE_DOCUMENT);
  5794. $conditionSession = api_get_session_condition($sessionId, true, false, 'd.session_id');
  5795. $courseId = $courseInfo['real_id'];
  5796. // get invisible folders
  5797. $sql = "SELECT DISTINCT d.id, path
  5798. FROM $itemPropertyTable i
  5799. INNER JOIN $documentTable d
  5800. ON (i.c_id = d.c_id)
  5801. WHERE
  5802. d.id = i.ref AND
  5803. i.tool = '".TOOL_DOCUMENT."'
  5804. $conditionSession AND
  5805. i.c_id = $courseId AND
  5806. d.c_id = $courseId ";
  5807. $result = Database::query($sql);
  5808. $documents = Database::store_result($result, 'ASSOC');
  5809. if ($documents) {
  5810. $course_dir = $courseInfo['directory'].'/document';
  5811. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  5812. $base_work_dir = $sys_course_path.$course_dir;
  5813. foreach ($documents as $document) {
  5814. $documentId = $document['id'];
  5815. self::delete_document(
  5816. $courseInfo,
  5817. null,
  5818. $base_work_dir,
  5819. $sessionId,
  5820. $documentId
  5821. );
  5822. }
  5823. }
  5824. $sql = "DELETE FROM $documentTable
  5825. WHERE c_id = $courseId AND session_id = $sessionId";
  5826. Database::query($sql);
  5827. $sql = "DELETE FROM $itemPropertyTable
  5828. WHERE c_id = $courseId AND session_id = $sessionId AND tool = '".TOOL_DOCUMENT."'";
  5829. Database::query($sql);
  5830. }
  5831. /**
  5832. * Update the file or directory path in the document db document table
  5833. *
  5834. * @author - Hugues Peeters <peeters@ipm.ucl.ac.be>
  5835. * @param - action (string) - action type require : 'delete' or 'update'
  5836. * @param - old_path (string) - old path info stored to change
  5837. * @param - new_path (string) - new path info to substitute
  5838. * @desc Update the file or directory path in the document db document table
  5839. *
  5840. */
  5841. public static function updateDbInfo($action, $old_path, $new_path = '')
  5842. {
  5843. $dbTable = Database::get_course_table(TABLE_DOCUMENT);
  5844. $course_id = api_get_course_int_id();
  5845. switch ($action) {
  5846. case 'delete':
  5847. $old_path = Database::escape_string($old_path);
  5848. $query = "DELETE FROM $dbTable
  5849. WHERE
  5850. c_id = $course_id AND
  5851. (
  5852. path LIKE BINARY '".$old_path."' OR
  5853. path LIKE BINARY '".$old_path."/%'
  5854. )";
  5855. Database::query($query);
  5856. break;
  5857. case 'update':
  5858. if ($new_path[0] == '.') {
  5859. $new_path = substr($new_path, 1);
  5860. }
  5861. $new_path = str_replace('//', '/', $new_path);
  5862. // Attempt to update - tested & working for root dir
  5863. $new_path = Database::escape_string($new_path);
  5864. $query = "UPDATE $dbTable SET
  5865. path = CONCAT('".$new_path."', SUBSTRING(path, LENGTH('".$old_path."')+1) )
  5866. WHERE c_id = $course_id AND (path LIKE BINARY '".$old_path."' OR path LIKE BINARY '".$old_path."/%')";
  5867. Database::query($query);
  5868. break;
  5869. }
  5870. }
  5871. }