document.lib.php 261 KB

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