document.lib.php 262 KB

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