document.lib.php 262 KB

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