document.lib.php 259 KB

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