document.lib.php 261 KB

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