document.lib.php 198 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063
  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. }
  256. //file without extension
  257. else {
  258. $extension = 'empty';
  259. }
  260. //if the extension is found, return the content type
  261. if (isset($mime_types[$extension])) {
  262. return $mime_types[$extension];
  263. }
  264. //else return octet-stream
  265. return 'application/octet-stream';
  266. }
  267. /**
  268. * @param string
  269. * @param string
  270. * @return true if the user is allowed to see the document, false otherwise
  271. * @author Sergio A Kessler, first version
  272. * @author Roan Embrechts, bugfix
  273. * @todo not only check if a file is visible, but also check if the user is allowed to see the file??
  274. */
  275. public static function file_visible_to_user($this_course, $doc_url)
  276. {
  277. $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
  278. if ($is_allowed_to_edit) {
  279. return true;
  280. } else {
  281. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  282. $tbl_item_property = $this_course . 'item_property';
  283. $doc_url = Database::escape_string($doc_url);
  284. $query = "SELECT 1 FROM $tbl_document AS docs,$tbl_item_property AS props
  285. WHERE
  286. props.tool = 'document' AND
  287. docs.id=props.ref AND
  288. props.visibility <> '1' AND
  289. docs.path = '$doc_url'";
  290. $result = Database::query($query);
  291. return (Database::num_rows($result) == 0);
  292. }
  293. }
  294. /**
  295. * This function streams a file to the client
  296. *
  297. * @param string $full_file_name
  298. * @param boolean $forced
  299. * @param string $name
  300. * @param string $fixLinksHttpToHttps change file content from http to https
  301. *
  302. * @return false if file doesn't exist, true if stream succeeded
  303. */
  304. public static function file_send_for_download(
  305. $full_file_name,
  306. $forced = false,
  307. $name = '',
  308. $fixLinksHttpToHttps = false
  309. ) {
  310. session_write_close(); //we do not need write access to session anymore
  311. if (!is_file($full_file_name)) {
  312. return false;
  313. }
  314. $filename = ($name == '') ? basename($full_file_name) : replace_dangerous_char($name);
  315. $len = filesize($full_file_name);
  316. // Fixing error when file name contains a ","
  317. $filename = str_replace(',', '', $filename);
  318. if ($forced) {
  319. // Force the browser to save the file instead of opening it
  320. global $_configuration;
  321. if (isset($_configuration['enable_x_sendfile_headers']) &&
  322. !empty($_configuration['enable_x_sendfile_headers'])) {
  323. header("X-Sendfile: $filename");
  324. }
  325. header('Content-type: application/octet-stream');
  326. header('Content-length: ' . $len);
  327. if (preg_match("/MSIE 5.5/", $_SERVER['HTTP_USER_AGENT'])) {
  328. header('Content-Disposition: filename= ' . $filename);
  329. } else {
  330. header('Content-Disposition: attachment; filename= ' . $filename);
  331. }
  332. if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
  333. header('Pragma: ');
  334. header('Cache-Control: ');
  335. header('Cache-Control: public'); // IE cannot download from sessions without a cache
  336. }
  337. header('Content-Description: ' . $filename);
  338. header('Content-Transfer-Encoding: binary');
  339. $res = fopen($full_file_name, 'r');
  340. fpassthru($res);
  341. return true;
  342. } else {
  343. //no forced download, just let the browser decide what to do according to the mimetype
  344. $content_type = self::file_get_mime_type($filename);
  345. 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. $encoding = @api_detect_encoding_html(file_get_contents($full_file_name));
  353. if (!empty($encoding)) {
  354. $content_type .= '; charset=' . $encoding;
  355. }
  356. break;
  357. case 'text/plain':
  358. $encoding = @api_detect_encoding(strip_tags(file_get_contents($full_file_name)));
  359. if (!empty($encoding)) {
  360. $content_type .= '; charset=' . $encoding;
  361. }
  362. break;
  363. case 'application/vnd.dwg':
  364. case 'application/vnd.dwf':
  365. header('Content-type: application/octet-stream');
  366. break;
  367. }
  368. header('Content-type: ' . $content_type);
  369. header('Content-Length: ' . $len);
  370. $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
  371. if (strpos($user_agent, 'msie')) {
  372. header('Content-Disposition: ; filename= ' . $filename);
  373. } else {
  374. header('Content-Disposition: inline; filename= ' . $filename);
  375. }
  376. if ($fixLinksHttpToHttps) {
  377. $content = file_get_contents($full_file_name);
  378. $content = str_replace(
  379. array('http%3A%2F%2F', 'http://'),
  380. array('https%3A%2F%2F', 'https://'),
  381. $content
  382. );
  383. echo $content;
  384. } else {
  385. readfile($full_file_name);
  386. }
  387. return true;
  388. }
  389. }
  390. /**
  391. * This function streams a string to the client for download.
  392. * You have to ensure that the calling script then stops processing (exit();)
  393. * otherwise it may cause subsequent use of the page to want to download
  394. * other pages in php rather than interpreting them.
  395. *
  396. * @param string $full_string The string contents
  397. * @param boolean $forced Whether "save" mode is forced (or opening directly authorized)
  398. * @param string $name The name of the file in the end (including extension)
  399. *
  400. * @return false if file doesn't exist, true if stream succeeded
  401. */
  402. public static function string_send_for_download($full_string, $forced = false, $name = '')
  403. {
  404. $filename = $name;
  405. $len = strlen($full_string);
  406. if ($forced) {
  407. //force the browser to save the file instead of opening it
  408. header('Content-type: application/octet-stream');
  409. //header('Content-Type: application/force-download');
  410. header('Content-length: ' . $len);
  411. if (preg_match("/MSIE 5.5/", $_SERVER['HTTP_USER_AGENT'])) {
  412. header('Content-Disposition: filename= ' . $filename);
  413. } else {
  414. header('Content-Disposition: attachment; filename= ' . $filename);
  415. }
  416. if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
  417. header('Pragma: ');
  418. header('Cache-Control: ');
  419. header('Cache-Control: public'); // IE cannot download from sessions without a cache
  420. }
  421. header('Content-Description: ' . $filename);
  422. header('Content-transfer-encoding: binary');
  423. echo $full_string;
  424. return true;
  425. //You have to ensure that the calling script then stops processing (exit();)
  426. //otherwise it may cause subsequent use of the page to want to download
  427. //other pages in php rather than interpreting them.
  428. } else {
  429. //no forced download, just let the browser decide what to do according to the mimetype
  430. $content_type = self::file_get_mime_type($filename);
  431. header('Expires: Wed, 01 Jan 1990 00:00:00 GMT');
  432. header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
  433. header('Cache-Control: no-cache, must-revalidate');
  434. header('Pragma: no-cache');
  435. switch ($content_type) {
  436. case 'text/html':
  437. $encoding = @api_detect_encoding_html($full_string);
  438. if (!empty($encoding)) {
  439. $content_type .= '; charset=' . $encoding;
  440. }
  441. break;
  442. case 'text/plain':
  443. $encoding = @api_detect_encoding(strip_tags($full_string));
  444. if (!empty($encoding)) {
  445. $content_type .= '; charset=' . $encoding;
  446. }
  447. break;
  448. }
  449. header('Content-type: ' . $content_type);
  450. header('Content-Length: ' . $len);
  451. $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
  452. if (strpos($user_agent, 'msie')) {
  453. header('Content-Disposition: ; filename= ' . $filename);
  454. } else {
  455. header('Content-Disposition: inline; filename= ' . $filename);
  456. }
  457. echo($full_string);
  458. //You have to ensure that the calling script then stops processing (exit();)
  459. //otherwise it may cause subsequent use of the page to want to download
  460. //other pages in php rather than interpreting them.
  461. return true;
  462. }
  463. }
  464. /**
  465. * Session folder filters
  466. *
  467. * @param string $path
  468. * @param int $sessionId
  469. *
  470. * @return null|string
  471. */
  472. public static function getSessionFolderFilters($path, $sessionId)
  473. {
  474. $sessionId = intval($sessionId);
  475. $condition = null;
  476. if (!empty($sessionId)) {
  477. // Chat folder filter
  478. if ($path == '/chat_files') {
  479. $condition .= " AND (id_session = '$sessionId') ";
  480. }
  481. // share_folder filter
  482. $condition .= " AND docs.path != '/shared_folder' ";
  483. }
  484. return $condition;
  485. }
  486. /**
  487. * Fetches all document data for the given user/group
  488. *
  489. * @param array $_course
  490. * @param string $path
  491. * @param int $to_group_id
  492. * @param int $to_user_id
  493. * @param boolean $can_see_invisible
  494. * @param boolean $search
  495. * @return array with all document data
  496. */
  497. public static function get_all_document_data(
  498. $_course,
  499. $path = '/',
  500. $to_group_id = 0,
  501. $to_user_id = null,
  502. $can_see_invisible = false,
  503. $search = false
  504. ) {
  505. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  506. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  507. if (!is_null($to_user_id)) {
  508. $to_field = 'last.to_user_id';
  509. $to_value = $to_user_id;
  510. } else {
  511. $to_field = 'last.to_group_id';
  512. $to_value = $to_group_id;
  513. }
  514. // Escape underscores in the path so they don't act as a wildcard
  515. $originalPath = $path;
  516. $path = str_replace('_', '\_', $path);
  517. $to_value = Database::escape_string($to_value);
  518. $visibility_bit = ' <> 2';
  519. // The given path will not end with a slash, unless it's the root '/'
  520. // so no root -> add slash
  521. $added_slash = $path == '/' ? '' : '/';
  522. // Condition for the session
  523. $sessionId = api_get_session_id();
  524. $condition_session = " AND (id_session = '$sessionId' OR (id_session = '0') )";
  525. $condition_session .= self::getSessionFolderFilters($originalPath, $sessionId);
  526. $sharedCondition = null;
  527. if ($originalPath == '/shared_folder') {
  528. $students = CourseManager::get_user_list_from_course_code($_course['code'], $sessionId);
  529. if (!empty($students)) {
  530. $conditionList = array();
  531. foreach ($students as $studentId => $studentInfo) {
  532. $conditionList[] = '/shared_folder/sf_user_' . $studentInfo['user_id'];
  533. }
  534. $sharedCondition .= ' AND docs.path IN ("' . implode('","', $conditionList) . '")';
  535. }
  536. }
  537. $sql = "SELECT
  538. docs.id,
  539. docs.filetype,
  540. docs.path,
  541. docs.title,
  542. docs.comment,
  543. docs.size,
  544. docs.readonly,
  545. docs.session_id,
  546. last.id_session item_property_session_id,
  547. last.lastedit_date,
  548. last.visibility,
  549. last.insert_user_id
  550. FROM $TABLE_ITEMPROPERTY AS last
  551. INNER JOIN $TABLE_DOCUMENT AS docs
  552. ON (
  553. docs.id = last.ref AND
  554. last.tool = '".TOOL_DOCUMENT."' AND
  555. docs.c_id = {$_course['real_id']} AND
  556. last.c_id = {$_course['real_id']}
  557. )
  558. WHERE
  559. docs.path LIKE '" . Database::escape_string($path . $added_slash.'%'). "' AND
  560. docs.path NOT LIKE '" . Database::escape_string($path . $added_slash.'%/%')."' AND
  561. docs.path NOT LIKE '%_DELETED_%' AND
  562. $to_field = $to_value AND
  563. last.visibility
  564. $visibility_bit
  565. $condition_session
  566. $sharedCondition
  567. ";
  568. $result = Database::query($sql);
  569. $doc_list = array();
  570. $document_data = array();
  571. $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
  572. $isCoach = api_is_coach();
  573. if ($result !== false && Database::num_rows($result) != 0) {
  574. while ($row = Database::fetch_array($result, 'ASSOC')) {
  575. if ($isCoach) {
  576. // Looking for course items that are invisible to hide it in the session
  577. if (in_array($row['id'], array_keys($doc_list))) {
  578. if ($doc_list[$row['id']]['item_property_session_id'] == 0 &&
  579. $doc_list[$row['id']]['session_id'] == 0
  580. ) {
  581. if ($doc_list[$row['id']]['visibility'] == 0) {
  582. unset($document_data[$row['id']]);
  583. continue;
  584. }
  585. }
  586. }
  587. $doc_list[$row['id']] = $row;
  588. }
  589. if (!$isCoach && !$is_allowed_to_edit) {
  590. $doc_list[] = $row;
  591. }
  592. if ($row['filetype'] == 'file' &&
  593. pathinfo($row['path'], PATHINFO_EXTENSION) == 'html'
  594. ) {
  595. // Templates management
  596. $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
  597. $sql = "SELECT id FROM $table_template
  598. WHERE
  599. course_code = '" . $_course['code'] . "' AND
  600. user_id = '".api_get_user_id()."' AND
  601. ref_doc = '".$row['id']."'";
  602. $template_result = Database::query($sql);
  603. $row['is_template'] = (Database::num_rows($template_result) > 0) ? 1 : 0;
  604. }
  605. // Just filling $document_data.
  606. $document_data[$row['id']] = $row;
  607. }
  608. // Only for the student we filter the results see BT#1652
  609. if (!$isCoach && !$is_allowed_to_edit) {
  610. $ids_to_remove = array();
  611. $my_repeat_ids = $temp = array();
  612. // Selecting repeated ids
  613. foreach ($doc_list as $row) {
  614. if (in_array($row['id'], array_keys($temp))) {
  615. $my_repeat_ids[] = $row['id'];
  616. }
  617. $temp[$row['id']] = $row;
  618. }
  619. //@todo use the DocumentManager::is_visible function
  620. // Checking visibility in a session
  621. foreach ($my_repeat_ids as $id) {
  622. foreach ($doc_list as $row) {
  623. if ($id == $row['id']) {
  624. if ($row['visibility'] == 0 && $row['item_property_session_id'] == 0) {
  625. $delete_repeated[$id] = true;
  626. }
  627. if ($row['visibility'] == 0 && $row['item_property_session_id'] != 0) {
  628. $delete_repeated[$id] = true;
  629. }
  630. }
  631. }
  632. }
  633. foreach ($doc_list as $key => $row) {
  634. if (in_array($row['visibility'], array('0', '2')) &&
  635. !in_array($row['id'], $my_repeat_ids)
  636. ) {
  637. $ids_to_remove[] = $row['id'];
  638. unset($doc_list[$key]);
  639. }
  640. }
  641. foreach ($document_data as $row) {
  642. if (in_array($row['id'], $ids_to_remove)) {
  643. unset($document_data[$row['id']]);
  644. }
  645. if (isset($delete_repeated[$row['id']]) && $delete_repeated[$row['id']]) {
  646. unset($document_data[$row['id']]);
  647. }
  648. }
  649. // Checking parents visibility.
  650. $final_document_data = array();
  651. foreach ($document_data as $row) {
  652. $is_visible = DocumentManager::check_visibility_tree(
  653. $row['id'],
  654. $_course['code'],
  655. $sessionId,
  656. api_get_user_id(),
  657. $to_group_id
  658. );
  659. if ($is_visible) {
  660. $final_document_data[$row['id']] = $row;
  661. }
  662. }
  663. } else {
  664. $final_document_data = $document_data;
  665. }
  666. return $final_document_data;
  667. } else {
  668. return false;
  669. }
  670. }
  671. /**
  672. * Gets the paths of all folders in a course
  673. * can show all folders (except for the deleted ones) or only visible ones
  674. *
  675. * @param array $_course
  676. * @param int $to_group_id
  677. * @param boolean $can_see_invisible
  678. *
  679. * @return array with paths
  680. */
  681. public static function get_all_document_folders(
  682. $_course,
  683. $to_group_id = 0,
  684. $can_see_invisible = false
  685. ) {
  686. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  687. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  688. $to_group_id = intval($to_group_id);
  689. $document_folders = array();
  690. $students = CourseManager::get_user_list_from_course_code(
  691. $_course['code'],
  692. api_get_session_id()
  693. );
  694. $sharedCondition = null;
  695. if (!empty($students)) {
  696. $conditionList = array();
  697. foreach ($students as $studentId => $studentInfo) {
  698. $conditionList[] = '/shared_folder/sf_user_' . $studentInfo['user_id'];
  699. }
  700. }
  701. if ($can_see_invisible) {
  702. // condition for the session
  703. $session_id = api_get_session_id();
  704. $condition_session = api_get_session_condition($session_id);
  705. $show_users_condition = "";
  706. if (api_get_setting('show_users_folders') == 'false') {
  707. $show_users_condition = " AND docs.path NOT LIKE '%shared_folder%'";
  708. }
  709. if ($to_group_id <> 0) {
  710. $sql = "SELECT DISTINCT docs.id, path
  711. FROM $TABLE_ITEMPROPERTY AS last
  712. INNER JOIN $TABLE_DOCUMENT AS docs
  713. ON (
  714. docs.id = last.ref AND
  715. last.tool = '" . TOOL_DOCUMENT . "' AND
  716. last.c_id = {$_course['real_id']} AND
  717. docs.c_id = {$_course['real_id']}
  718. )
  719. WHERE
  720. docs.filetype = 'folder' AND
  721. last.to_group_id = " . $to_group_id . " AND
  722. docs.path NOT LIKE '%shared_folder%' AND
  723. docs.path NOT LIKE '%_DELETED_%' AND
  724. last.visibility <> 2 $condition_session ";
  725. } else {
  726. $sql = "SELECT DISTINCT docs.id, path
  727. FROM $TABLE_ITEMPROPERTY AS last
  728. INNER JOIN $TABLE_DOCUMENT AS docs
  729. ON (
  730. docs.id = last.ref AND
  731. last.tool = '" . TOOL_DOCUMENT . "' AND
  732. last.c_id = {$_course['real_id']} AND
  733. docs.c_id = {$_course['real_id']}
  734. )
  735. WHERE
  736. docs.filetype = 'folder' AND
  737. docs.path NOT LIKE '%_DELETED_%' AND
  738. last.to_group_id = 0 AND
  739. last.visibility <> 2
  740. $show_users_condition $condition_session ";
  741. }
  742. $result = Database::query($sql);
  743. if ($result && Database::num_rows($result) != 0) {
  744. while ($row = Database::fetch_array($result, 'ASSOC')) {
  745. if (DocumentManager::is_folder_to_avoid($row['path'])) {
  746. continue;
  747. }
  748. if (strpos($row['path'], '/shared_folder/') !== false) {
  749. if (!in_array($row['path'], $conditionList)) {
  750. continue;
  751. }
  752. }
  753. $document_folders[$row['id']] = $row['path'];
  754. }
  755. if (!empty($document_folders)) {
  756. natsort($document_folders);
  757. }
  758. return $document_folders;
  759. } else {
  760. return false;
  761. }
  762. } else {
  763. // No invisible folders
  764. // Condition for the session
  765. $session_id = api_get_session_id();
  766. $condition_session = api_get_session_condition($session_id);
  767. //get visible folders
  768. $sql = "SELECT DISTINCT docs.id, path
  769. FROM
  770. $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
  771. WHERE
  772. docs.id = last.ref AND
  773. docs.filetype = 'folder' AND
  774. last.tool = '" . TOOL_DOCUMENT . "' AND
  775. last.to_group_id = " . $to_group_id . " AND
  776. last.visibility = 1 $condition_session AND
  777. last.c_id = {$_course['real_id']} AND
  778. docs.c_id = {$_course['real_id']} ";
  779. $result = Database::query($sql);
  780. $visibleFolders = array();
  781. while ($row = Database::fetch_array($result, 'ASSOC')) {
  782. $visibleFolders[$row['id']] = $row['path'];
  783. }
  784. // Condition for the session
  785. $session_id = api_get_session_id();
  786. $condition_session = api_get_session_condition($session_id);
  787. //get invisible folders
  788. $sql = "SELECT DISTINCT docs.id, path
  789. FROM $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
  790. WHERE
  791. docs.id = last.ref AND
  792. docs.filetype = 'folder' AND
  793. last.tool = '" . TOOL_DOCUMENT . "' AND
  794. last.to_group_id = " . $to_group_id . " AND
  795. last.visibility = 0 $condition_session AND
  796. last.c_id = {$_course['real_id']} AND
  797. docs.c_id = {$_course['real_id']} ";
  798. $result = Database::query($sql);
  799. $invisibleFolders = array();
  800. while ($row = Database::fetch_array($result, 'ASSOC')) {
  801. //condition for the session
  802. $session_id = api_get_session_id();
  803. $condition_session = api_get_session_condition($session_id);
  804. //get visible folders in the invisible ones -> they are invisible too
  805. $sql = "SELECT DISTINCT docs.id, path
  806. FROM $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
  807. WHERE
  808. docs.id = last.ref AND
  809. docs.path LIKE '" . Database::escape_string($row['path'].'/%') . "' AND
  810. docs.filetype = 'folder' AND
  811. last.tool = '" . TOOL_DOCUMENT . "' AND
  812. last.to_group_id = " . $to_group_id . " AND
  813. last.visibility = 1 $condition_session AND
  814. last.c_id = {$_course['real_id']} AND
  815. docs.c_id = {$_course['real_id']} ";
  816. $folder_in_invisible_result = Database::query($sql);
  817. while ($folders_in_invisible_folder = Database::fetch_array($folder_in_invisible_result, 'ASSOC')) {
  818. $invisibleFolders[$folders_in_invisible_folder['id']] = $folders_in_invisible_folder['path'];
  819. }
  820. }
  821. //if both results are arrays -> //calculate the difference between the 2 arrays -> only visible folders are left :)
  822. if (is_array($visibleFolders) && is_array($invisibleFolders)) {
  823. $document_folders = array_diff($visibleFolders, $invisibleFolders);
  824. natsort($document_folders);
  825. return $document_folders;
  826. } elseif (is_array($visibleFolders)) {
  827. natsort($visibleFolders);
  828. return $visibleFolders;
  829. } else {
  830. //no visible folders found
  831. return false;
  832. }
  833. }
  834. }
  835. /**
  836. * This check if a document has the readonly property checked, then see if the user
  837. * is the owner of this file, if all this is true then return true.
  838. *
  839. * @param array $_course
  840. * @param int $user_id id of the current user
  841. * @param string $file path stored in the database (if not defined, $documentId must be used)
  842. * @param int $document_id in case you dont have the file path ,
  843. * insert the id of the file here and leave $file in blank ''
  844. * @param bool $to_delete
  845. * @param int $sessionId
  846. * @return boolean true/false
  847. * */
  848. public static function check_readonly(
  849. $_course,
  850. $user_id,
  851. $file = null,
  852. $document_id = '',
  853. $to_delete = false,
  854. $sessionId = null,
  855. $documentId = null
  856. ) {
  857. if (empty($sessionId)) {
  858. $sessionId = api_get_session_id();
  859. } else {
  860. $sessionId = intval($sessionId);
  861. }
  862. if (empty($document_id) || !is_numeric($document_id)) {
  863. $document_id = self::get_document_id($_course, $file, $sessionId);
  864. } else {
  865. $document_id = intval($document_id);
  866. }
  867. $TABLE_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  868. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  869. $course_id = $_course['real_id'];
  870. if ($to_delete) {
  871. if (self::is_folder($_course, $document_id)) {
  872. if (!empty($file)) {
  873. $path = Database::escape_string($file);
  874. // Check
  875. $sql = "SELECT td.id, readonly, tp.insert_user_id
  876. FROM $TABLE_DOCUMENT td, $TABLE_PROPERTY tp
  877. WHERE
  878. td.c_id = $course_id AND
  879. tp.c_id = $course_id AND
  880. td.session_id = $sessionId AND
  881. tp.ref= td.id AND
  882. (path='" . $path . "' OR path LIKE BINARY '" . $path . "/%' ) ";
  883. // Get all id's of documents that are deleted
  884. $what_to_check_result = Database::query($sql);
  885. if ($what_to_check_result && Database::num_rows($what_to_check_result) != 0) {
  886. // file with readonly set to 1 exist?
  887. $readonly_set = false;
  888. while ($row = Database::fetch_array($what_to_check_result)) {
  889. //query to delete from item_property table
  890. if ($row['readonly'] == 1) {
  891. if (!($row['insert_user_id'] == $user_id)) {
  892. $readonly_set = true;
  893. break;
  894. }
  895. }
  896. }
  897. if ($readonly_set) {
  898. return true;
  899. }
  900. }
  901. }
  902. return false;
  903. }
  904. }
  905. if (!empty($document_id)) {
  906. $sql = "SELECT a.insert_user_id, b.readonly
  907. FROM $TABLE_PROPERTY a, $TABLE_DOCUMENT b
  908. WHERE
  909. a.c_id = $course_id AND
  910. b.c_id = $course_id AND
  911. a.ref = b.id and a.ref = $document_id LIMIT 1";
  912. $result = Database::query($sql);
  913. $doc_details = Database ::fetch_array($result, 'ASSOC');
  914. if ($doc_details['readonly'] == 1) {
  915. return !($doc_details['insert_user_id'] == $user_id || api_is_platform_admin());
  916. }
  917. }
  918. return false;
  919. }
  920. /**
  921. * This check if a document is a folder or not
  922. * @param array $_course
  923. * @param int $document_id of the item
  924. * @return boolean true/false
  925. * */
  926. public static function is_folder($_course, $document_id)
  927. {
  928. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  929. $course_id = $_course['real_id'];
  930. $document_id = intval($document_id);
  931. $sql = "SELECT filetype FROM $TABLE_DOCUMENT
  932. WHERE c_id = $course_id AND id= $document_id";
  933. $result = Database::fetch_array(Database::query($sql), 'ASSOC');
  934. return $result['filetype'] == 'folder';
  935. }
  936. /**
  937. * @param int $document_id
  938. * @param array $course_info
  939. * @param int $session_id
  940. * @param bool $remove_content_from_db
  941. */
  942. public static function deleteDocumentFromDb(
  943. $document_id,
  944. $course_info = array(),
  945. $session_id = 0,
  946. $remove_content_from_db = false
  947. ) {
  948. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  949. $TABLE_ITEMPROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  950. // Deleting from the DB
  951. $user_id = api_get_user_id();
  952. $document_id = intval($document_id);
  953. if (empty($course_info)) {
  954. $course_info = api_get_course_info();
  955. }
  956. if (empty($session_id)) {
  957. $session_id = api_get_session_id();
  958. }
  959. // Soft DB delete
  960. api_item_property_update(
  961. $course_info,
  962. TOOL_DOCUMENT,
  963. $document_id,
  964. 'delete',
  965. $user_id,
  966. null,
  967. null,
  968. null,
  969. null,
  970. $session_id
  971. );
  972. self::delete_document_from_search_engine($course_info['code'], $document_id);
  973. self::unset_document_as_template($document_id, $course_info['code'], $user_id);
  974. //Hard DB delete
  975. if ($remove_content_from_db) {
  976. $sql = "DELETE FROM $TABLE_ITEMPROPERTY
  977. WHERE
  978. c_id = {$course_info['real_id']} AND
  979. ref = ".$document_id." AND
  980. tool='".TOOL_DOCUMENT."'";
  981. Database::query($sql);
  982. $sql = "DELETE FROM $TABLE_DOCUMENT
  983. WHERE c_id = {$course_info['real_id']} AND id = ".$document_id;
  984. Database::query($sql);
  985. self::delete_document_metadata($document_id);
  986. }
  987. }
  988. /**
  989. * @param int $document_id
  990. */
  991. public static function delete_document_metadata($document_id)
  992. {
  993. // needed to deleted medadata
  994. require_once api_get_path(SYS_CODE_PATH) . 'metadata/md_funcs.php';
  995. require_once api_get_path(LIBRARY_PATH) . 'fileManage.lib.php';
  996. $mdStore = new mdstore(true);
  997. //delete metadata
  998. $eid = 'Document' . '.' . $document_id;
  999. $mdStore->mds_delete($eid);
  1000. $mdStore->mds_delete_offspring($eid);
  1001. }
  1002. /**
  1003. * This deletes a document by changing visibility to 2, renaming it to filename_DELETED_#id
  1004. * Files/folders that are inside a deleted folder get visibility 2
  1005. *
  1006. * @param array $_course
  1007. * @param string $path, path stored in the database
  1008. * @param string $base_work_dir, path to the documents folder (if not defined, $documentId must be used)
  1009. * @param int $sessionId The ID of the session, if any
  1010. * @param int $documentId The document id, if available
  1011. * @param int $groupId
  1012. * @return boolean true/false
  1013. * @todo now only files/folders in a folder get visibility 2, we should rename them too.
  1014. * @todo We should be able to get rid of this later when using only documentId (check further usage)
  1015. */
  1016. public static function delete_document(
  1017. $_course,
  1018. $path = null,
  1019. $base_work_dir,
  1020. $sessionId = null,
  1021. $documentId = null,
  1022. $groupId = null
  1023. ) {
  1024. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  1025. if (empty($groupId)) {
  1026. $groupId = api_get_group_id();
  1027. } else {
  1028. $groupId = intval($groupId);
  1029. }
  1030. if (empty($sessionId)) {
  1031. $sessionId = api_get_session_id();
  1032. } else {
  1033. $sessionId = intval($sessionId);
  1034. }
  1035. $course_id = $_course['real_id'];
  1036. if (empty($course_id)) {
  1037. return false;
  1038. }
  1039. if (empty($base_work_dir)) {
  1040. return false;
  1041. }
  1042. if (empty($documentId)) {
  1043. $documentId = self::get_document_id($_course, $path, $sessionId);
  1044. $docInfo = self::get_document_data_by_id(
  1045. $documentId,
  1046. $_course['code'],
  1047. false,
  1048. $sessionId
  1049. );
  1050. $path = $docInfo['path'];
  1051. } else {
  1052. $docInfo = self::get_document_data_by_id(
  1053. $documentId,
  1054. $_course['code'],
  1055. false,
  1056. $sessionId
  1057. );
  1058. if (empty($docInfo)) {
  1059. return false;
  1060. }
  1061. $path = $docInfo['path'];
  1062. }
  1063. $documentId = intval($documentId);
  1064. if (empty($path) || empty($docInfo) || empty($documentId)) {
  1065. return false;
  1066. }
  1067. $itemInfo = api_get_item_property_info(
  1068. $_course['real_id'],
  1069. TOOL_DOCUMENT,
  1070. $documentId,
  1071. $sessionId
  1072. );
  1073. if (empty($itemInfo)) {
  1074. return false;
  1075. }
  1076. // File was already deleted.
  1077. if ($itemInfo['lastedit_type'] == 'DocumentDeleted' ||
  1078. $itemInfo['lastedit_type'] == 'delete' ||
  1079. $itemInfo['visibility'] == 2
  1080. ) {
  1081. return false;
  1082. }
  1083. // Filtering by group.
  1084. if ($itemInfo['to_group_id'] != $groupId) {
  1085. return false;
  1086. }
  1087. $document_exists_in_disk = file_exists($base_work_dir.$path);
  1088. $new_path = $path.'_DELETED_'.$documentId;
  1089. $file_deleted_from_db = false;
  1090. $file_deleted_from_disk = false;
  1091. $file_renamed_from_disk = false;
  1092. if ($documentId) {
  1093. // Deleting doc from the DB.
  1094. self::deleteDocumentFromDb($documentId, $_course, $sessionId);
  1095. // Checking
  1096. // $file_exists_in_db = self::get_document_data_by_id($documentId, $_course['code']);
  1097. $file_deleted_from_db = true;
  1098. }
  1099. // Looking for children.
  1100. if ($docInfo['filetype'] == 'folder') {
  1101. $cleanPath = Database::escape_string($path);
  1102. // Deleted files inside this folder.
  1103. $sql = "SELECT id FROM $TABLE_DOCUMENT
  1104. WHERE
  1105. c_id = $course_id AND
  1106. session_id = $sessionId AND
  1107. path LIKE BINARY '".$cleanPath."/%'";
  1108. // Get all id's of documents that are deleted.
  1109. $result = Database::query($sql);
  1110. if ($result && Database::num_rows($result) != 0) {
  1111. // Recursive delete.
  1112. while ($row = Database::fetch_array($result)) {
  1113. self::delete_document(
  1114. $_course,
  1115. null,
  1116. $base_work_dir,
  1117. $sessionId,
  1118. $row['id']
  1119. );
  1120. }
  1121. }
  1122. }
  1123. if ($document_exists_in_disk) {
  1124. if (api_get_setting('permanently_remove_deleted_files') == 'true') {
  1125. // Delete documents, do it like this so metadata gets deleted too
  1126. my_delete($base_work_dir.$path);
  1127. // Hard delete.
  1128. self::deleteDocumentFromDb($documentId, $_course, $sessionId, true);
  1129. $file_deleted_from_disk = true;
  1130. } else {
  1131. // Set visibility to 2 and rename file/folder to xxx_DELETED_#id (soft delete)
  1132. if (is_file($base_work_dir.$path) || is_dir($base_work_dir.$path)) {
  1133. if (rename($base_work_dir.$path, $base_work_dir.$new_path)) {
  1134. $new_path = Database::escape_string($new_path);
  1135. $sql = "UPDATE $TABLE_DOCUMENT
  1136. SET path = '".$new_path."'
  1137. WHERE
  1138. c_id = $course_id AND
  1139. session_id = $sessionId AND
  1140. id = ".$documentId;
  1141. Database::query($sql);
  1142. // Soft delete.
  1143. self::deleteDocumentFromDb($documentId, $_course, $sessionId);
  1144. // Change path of sub folders and documents in database.
  1145. $old_item_path = $docInfo['path'];
  1146. $new_item_path = $new_path.substr($old_item_path, strlen($path));
  1147. $new_item_path = Database::escape_string($new_item_path);
  1148. $sql = "UPDATE $TABLE_DOCUMENT
  1149. SET path = '".$new_item_path."'
  1150. WHERE
  1151. c_id = $course_id AND
  1152. session_id = $sessionId AND
  1153. id = ".$documentId;
  1154. Database::query($sql);
  1155. $file_renamed_from_disk = true;
  1156. } else {
  1157. // Couldn't rename - file permissions problem?
  1158. error_log(
  1159. __FILE__.' '.__LINE__.': Error renaming '.$base_work_dir.$path.' to '.$base_work_dir.$new_path.'. This is probably due to file permissions',
  1160. 0
  1161. );
  1162. }
  1163. }
  1164. }
  1165. }
  1166. // Checking inconsistency
  1167. //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').')');
  1168. if ($file_deleted_from_db && $file_deleted_from_disk ||
  1169. $file_deleted_from_db && $file_renamed_from_disk
  1170. ) {
  1171. return true;
  1172. } else {
  1173. //Something went wrong
  1174. //The file or directory isn't there anymore (on the filesystem)
  1175. // This means it has been removed externally. To prevent a
  1176. // blocking error from happening, we drop the related items from the
  1177. // item_property and the document table.
  1178. error_log(
  1179. __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',
  1180. 0
  1181. );
  1182. return false;
  1183. }
  1184. }
  1185. /**
  1186. * Removes documents from search engine database
  1187. *
  1188. * @param string $course_id Course code
  1189. * @param int $document_id Document id to delete
  1190. */
  1191. public static function delete_document_from_search_engine($course_id, $document_id)
  1192. {
  1193. // remove from search engine if enabled
  1194. if (api_get_setting('search_enabled') == 'true') {
  1195. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  1196. $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  1197. $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
  1198. $res = Database::query($sql);
  1199. if (Database::num_rows($res) > 0) {
  1200. $row2 = Database::fetch_array($res);
  1201. require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
  1202. $di = new ChamiloIndexer();
  1203. $di->remove_document((int) $row2['search_did']);
  1204. }
  1205. $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  1206. $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
  1207. Database::query($sql);
  1208. // remove terms from db
  1209. require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
  1210. delete_all_values_for_item($course_id, TOOL_DOCUMENT, $document_id);
  1211. }
  1212. }
  1213. /**
  1214. * Gets the id of a document with a given path
  1215. *
  1216. * @param array $courseInfo
  1217. * @param string $path
  1218. * @param int $sessionId
  1219. * @return int id of document / false if no doc found
  1220. */
  1221. public static function get_document_id($courseInfo, $path, $sessionId = null)
  1222. {
  1223. $table = Database :: get_course_table(TABLE_DOCUMENT);
  1224. $courseId = $courseInfo['real_id'];
  1225. if (!isset($sessionId)) {
  1226. $sessionId = api_get_session_id();
  1227. } else {
  1228. $sessionId = intval($sessionId);
  1229. }
  1230. $path = Database::escape_string($path);
  1231. if (!empty($courseId) && !empty($path)) {
  1232. $sql = "SELECT id FROM $table
  1233. WHERE
  1234. c_id = $courseId AND
  1235. path LIKE BINARY '$path' AND
  1236. session_id = $sessionId
  1237. LIMIT 1";
  1238. $result = Database::query($sql);
  1239. if (Database::num_rows($result)) {
  1240. $row = Database::fetch_array($result);
  1241. return intval($row['id']);
  1242. }
  1243. }
  1244. return false;
  1245. }
  1246. /**
  1247. * Gets the document data with a given id
  1248. *
  1249. * @param int $id Document Id (id field in c_document table)
  1250. * @param string $course_code Course code
  1251. * @param bool $load_parents load folder parents.
  1252. * @param int $session_id The session ID,
  1253. * 0 if requires context *out of* session, and null to use global context
  1254. * @return array document content
  1255. */
  1256. public static function get_document_data_by_id(
  1257. $id,
  1258. $course_code,
  1259. $load_parents = false,
  1260. $session_id = null
  1261. ) {
  1262. $course_info = api_get_course_info($course_code);
  1263. $course_id = $course_info['real_id'];
  1264. if (empty($course_info)) {
  1265. return false;
  1266. }
  1267. if (isset($session_id)) {
  1268. $session_id = intval($session_id);
  1269. } else {
  1270. $session_id = api_get_session_id();
  1271. }
  1272. $www = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/document';
  1273. $TABLE_DOCUMENT = Database :: get_course_table(TABLE_DOCUMENT);
  1274. $id = intval($id);
  1275. $sql = "SELECT * FROM $TABLE_DOCUMENT
  1276. WHERE c_id = $course_id AND session_id = $session_id AND id = $id";
  1277. $result = Database::query($sql);
  1278. if ($result && Database::num_rows($result) == 1) {
  1279. $row = Database::fetch_array($result, 'ASSOC');
  1280. //@todo need to clarify the name of the URLs not nice right now
  1281. $url_path = urlencode($row['path']);
  1282. $path = str_replace('%2F', '/', $url_path);
  1283. $pathinfo = pathinfo($row['path']);
  1284. $row['url'] = api_get_path(WEB_CODE_PATH) . 'document/showinframes.php?cidReq=' . $course_code . '&id=' . $id;
  1285. $row['document_url'] = api_get_path(WEB_CODE_PATH) . 'document/document.php?cidReq=' . $course_code . '&id=' . $id;
  1286. $row['absolute_path'] = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
  1287. $row['absolute_path_from_document'] = '/document' . $row['path'];
  1288. $row['absolute_parent_path'] = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$pathinfo['dirname'] . '/';
  1289. $row['direct_url'] = $www . $path;
  1290. if (dirname($row['path']) == '.') {
  1291. $row['parent_id'] = '0';
  1292. } else {
  1293. $row['parent_id'] = self::get_document_id($course_info, dirname($row['path']), $session_id);
  1294. }
  1295. $parents = array();
  1296. //Use to generate parents (needed for the breadcrumb)
  1297. //@todo sorry but this for is here because there's not a parent_id in the document table so we parsed the path!!
  1298. if ($load_parents) {
  1299. $dir_array = explode('/', $row['path']);
  1300. $dir_array = array_filter($dir_array);
  1301. $array_len = count($dir_array) + 1;
  1302. $real_dir = '';
  1303. for ($i = 1; $i < $array_len; $i++) {
  1304. $real_dir .= '/' . $dir_array[$i];
  1305. $parent_id = self::get_document_id($course_info, $real_dir);
  1306. if ($session_id != 0 && empty($parent_id)) {
  1307. $parent_id = self::get_document_id($course_info, $real_dir, 0);
  1308. }
  1309. if (!empty($parent_id)) {
  1310. $sub_document_data = self::get_document_data_by_id(
  1311. $parent_id,
  1312. $course_code,
  1313. false,
  1314. $session_id
  1315. );
  1316. if ($session_id != 0 and !$sub_document_data) {
  1317. $sub_document_data = self::get_document_data_by_id(
  1318. $parent_id,
  1319. $course_code,
  1320. false,
  1321. 0
  1322. );
  1323. }
  1324. //@todo add visibility here
  1325. $parents[] = $sub_document_data;
  1326. }
  1327. }
  1328. }
  1329. $row['parents'] = $parents;
  1330. return $row;
  1331. }
  1332. return false;
  1333. }
  1334. /**
  1335. * Allow to set a specific document as a new template for FCKEditor
  1336. * for a particular user in a particular course
  1337. *
  1338. * @param string $title
  1339. * @param string $description
  1340. * @param int $document_id_for_template the document id
  1341. * @param string $course_code
  1342. * @param int $user_id
  1343. */
  1344. public static function set_document_as_template($title, $description, $document_id_for_template, $course_code, $user_id, $image)
  1345. {
  1346. // Database table definition
  1347. $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
  1348. // creating the sql statement
  1349. $sql = "INSERT INTO $table_template
  1350. (title, description, course_code, user_id, ref_doc, image)
  1351. VALUES (
  1352. '" . Database::escape_string($title) . "',
  1353. '" . Database::escape_string($description) . "',
  1354. '" . Database::escape_string($course_code) . "',
  1355. '" . intval($user_id) . "',
  1356. '" . Database::escape_string($document_id_for_template) . "',
  1357. '" . Database::escape_string($image) . "')";
  1358. Database::query($sql);
  1359. return true;
  1360. }
  1361. /**
  1362. * Unset a document as template
  1363. *
  1364. * @param int $document_id
  1365. * @param string $course_code
  1366. * @param int $user_id
  1367. */
  1368. public static function unset_document_as_template($document_id, $course_code, $user_id)
  1369. {
  1370. $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
  1371. $course_code = Database::escape_string($course_code);
  1372. $user_id = intval($user_id);
  1373. $document_id = intval($document_id);
  1374. $sql = 'SELECT id FROM ' . $table_template . '
  1375. WHERE
  1376. course_code="' . $course_code . '" AND
  1377. user_id="' . $user_id . '" AND
  1378. ref_doc="' . $document_id . '"';
  1379. $result = Database::query($sql);
  1380. $template_id = Database::result($result, 0, 0);
  1381. include_once(api_get_path(LIBRARY_PATH) . 'fileManage.lib.php');
  1382. my_delete(api_get_path(SYS_CODE_PATH) . 'upload/template_thumbnails/' . $template_id . '.jpg');
  1383. $sql = 'DELETE FROM ' . $table_template . '
  1384. WHERE
  1385. course_code="' . $course_code . '" AND
  1386. user_id="' . $user_id . '" AND
  1387. ref_doc="' . $document_id . '"';
  1388. Database::query($sql);
  1389. }
  1390. /**
  1391. * Return true if the documentpath have visibility=1 as
  1392. * item_property (you should use the is_visible_by_id)
  1393. *
  1394. * @param string $document_path the relative complete path of the document
  1395. * @param array $course the _course array info of the document's course
  1396. * @param int
  1397. * @param string
  1398. */
  1399. public static function is_visible($doc_path, $course, $session_id = 0, $file_type = 'file')
  1400. {
  1401. $docTable = Database::get_course_table(TABLE_DOCUMENT);
  1402. $propTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
  1403. $course_id = $course['real_id'];
  1404. //note the extra / at the end of doc_path to match every path in the document table that is part of the document path
  1405. $session_id = intval($session_id);
  1406. $condition = "AND id_session IN ('$session_id', '0') ";
  1407. // The " d.filetype='file' " let the user see a file even if the folder is hidden see #2198
  1408. /*
  1409. When using hotpotatoes files, a new html files are generated
  1410. in the hotpotatoes folder to display the test.
  1411. The genuine html file is copied to math4.htm(user_id).t.html
  1412. Images files are not copied, and keep same name.
  1413. To check the html file visibility, we don't have to check file math4.htm(user_id).t.html but file math4.htm
  1414. In this case, we have to remove (user_id).t.html to check the visibility of the file
  1415. For images, we just check the path of the image file.
  1416. Exemple of hotpotatoes folder :
  1417. A.jpg
  1418. maths4-consigne.jpg
  1419. maths4.htm
  1420. maths4.htm1.t.html
  1421. maths4.htm52.t.html
  1422. maths4.htm654.t.html
  1423. omega.jpg
  1424. theta.jpg
  1425. */
  1426. if (strpos($doc_path, 'HotPotatoes_files') && preg_match("/\.t\.html$/", $doc_path)) {
  1427. $doc_path = substr($doc_path, 0, strlen($doc_path) - 7 - strlen(api_get_user_id()));
  1428. }
  1429. if (!in_array($file_type, array('file', 'folder'))) {
  1430. $file_type = 'file';
  1431. }
  1432. $sql = "SELECT visibility
  1433. FROM $docTable d
  1434. INNER JOIN $propTable ip
  1435. ON (d.id = ip.ref AND d.c_id = ip.c_id)
  1436. WHERE
  1437. ip.visibility <> 2 AND
  1438. d.c_id = $course_id AND
  1439. ip.tool = '" . TOOL_DOCUMENT . "' $condition AND
  1440. filetype = '$file_type' AND
  1441. locate(concat(path,'/'), '" . Database::escape_string($doc_path.'/'). "')=1
  1442. ";
  1443. $result = Database::query($sql);
  1444. $is_visible = false;
  1445. if (Database::num_rows($result) > 0) {
  1446. $row = Database::fetch_array($result, 'ASSOC');
  1447. if ($row['visibility'] == 1) {
  1448. $is_visible = $_SESSION['is_allowed_in_course'] || api_is_platform_admin();
  1449. }
  1450. }
  1451. /* improved protection of documents viewable directly through the url:
  1452. incorporates the same protections of the course at the url of
  1453. documents:
  1454. access allowed for the whole world Open, access allowed for
  1455. users registered on the platform Private access, document accessible
  1456. only to course members (see the Users list), Completely closed;
  1457. the document is only accessible to the course admin and
  1458. teaching assistants.*/
  1459. //return $_SESSION ['is_allowed_in_course'] || api_is_platform_admin();
  1460. return $is_visible;
  1461. }
  1462. /**
  1463. * Return true if user can see a file
  1464. *
  1465. * @param int document id
  1466. * @param array course info
  1467. * @param int
  1468. * @param int
  1469. * @param bool
  1470. * @return bool
  1471. */
  1472. public static function is_visible_by_id(
  1473. $doc_id,
  1474. $course_info,
  1475. $session_id,
  1476. $user_id,
  1477. $admins_can_see_everything = true
  1478. ) {
  1479. $user_in_course = false;
  1480. //1. Checking the course array
  1481. if (empty($course_info)) {
  1482. $course_info = api_get_course_info();
  1483. if (empty($course_info)) {
  1484. return false;
  1485. }
  1486. }
  1487. $doc_id = intval($doc_id);
  1488. $session_id = intval($session_id);
  1489. //2. Course and Session visibility are handle in local.inc.php/global.inc.php
  1490. //3. Checking if user exist in course/session
  1491. if ($session_id == 0) {
  1492. if (CourseManager::is_user_subscribed_in_course(
  1493. $user_id,
  1494. $course_info['code']
  1495. ) ||
  1496. api_is_platform_admin()
  1497. ) {
  1498. $user_in_course = true;
  1499. }
  1500. // Check if course is open then we can consider that the student is registered to the course
  1501. if (isset($course_info) &&
  1502. in_array(
  1503. $course_info['visibility'],
  1504. array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD)
  1505. )
  1506. ) {
  1507. $user_in_course = true;
  1508. }
  1509. } else {
  1510. $user_status = SessionManager::get_user_status_in_course_session(
  1511. $user_id,
  1512. $course_info['code'],
  1513. $session_id
  1514. );
  1515. if (in_array($user_status, array('0', '2', '6'))) {
  1516. //is true if is an student, course session teacher or coach
  1517. $user_in_course = true;
  1518. }
  1519. if (api_is_platform_admin()) {
  1520. $user_in_course = true;
  1521. }
  1522. }
  1523. // 4. Checking document visibility (i'm repeating the code in order to be more clear when reading ) - jm
  1524. if ($user_in_course) {
  1525. // 4.1 Checking document visibility for a Course
  1526. if ($session_id == 0) {
  1527. $item_info = api_get_item_property_info($course_info['real_id'], 'document', $doc_id, 0);
  1528. if (isset($item_info['visibility'])) {
  1529. // True for admins if document exists
  1530. if ($admins_can_see_everything && api_is_platform_admin()) {
  1531. return true;
  1532. }
  1533. if ($item_info['visibility'] == 1) {
  1534. return true;
  1535. }
  1536. }
  1537. } else {
  1538. // 4.2 Checking document visibility for a Course in a Session
  1539. $item_info = api_get_item_property_info(
  1540. $course_info['real_id'],
  1541. 'document',
  1542. $doc_id,
  1543. 0
  1544. );
  1545. $item_info_in_session = api_get_item_property_info(
  1546. $course_info['real_id'],
  1547. 'document',
  1548. $doc_id,
  1549. $session_id
  1550. );
  1551. // True for admins if document exists
  1552. if (isset($item_info['visibility'])) {
  1553. if ($admins_can_see_everything && api_is_platform_admin())
  1554. return true;
  1555. }
  1556. if (isset($item_info_in_session['visibility'])) {
  1557. if ($item_info_in_session['visibility'] == 1) {
  1558. return true;
  1559. }
  1560. } else {
  1561. if ($item_info['visibility'] == 1) {
  1562. return true;
  1563. }
  1564. }
  1565. }
  1566. } elseif ($admins_can_see_everything && api_is_platform_admin()) {
  1567. return true;
  1568. }
  1569. return false;
  1570. }
  1571. /**
  1572. * Allow attach a certificate to a course
  1573. * @param string The course id
  1574. * @param int The document id
  1575. * @return void()
  1576. */
  1577. public static function attach_gradebook_certificate($course_id, $document_id)
  1578. {
  1579. $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1580. $session_id = api_get_session_id();
  1581. if ($session_id == 0 || is_null($session_id)) {
  1582. $sql_session = 'AND (session_id=' . intval($session_id) . ' OR isnull(session_id)) ';
  1583. } elseif ($session_id > 0) {
  1584. $sql_session = 'AND session_id=' . intval($session_id);
  1585. } else {
  1586. $sql_session = '';
  1587. }
  1588. $sql = 'UPDATE ' . $tbl_category . ' SET document_id="' . intval($document_id) . '"
  1589. WHERE course_code="' . Database::escape_string($course_id) . '" ' . $sql_session;
  1590. Database::query($sql);
  1591. }
  1592. /**
  1593. * get the document id of default certificate
  1594. * @param string $course_id
  1595. * @return int The default certificate id
  1596. */
  1597. public static function get_default_certificate_id($course_id)
  1598. {
  1599. $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1600. $session_id = api_get_session_id();
  1601. if ($session_id == 0 || is_null($session_id)) {
  1602. $sql_session = 'AND (session_id=' . intval($session_id) . ' OR isnull(session_id)) ';
  1603. } elseif ($session_id > 0) {
  1604. $sql_session = 'AND session_id=' . intval($session_id);
  1605. } else {
  1606. $sql_session = '';
  1607. }
  1608. $sql = 'SELECT document_id FROM ' . $tbl_category . '
  1609. WHERE course_code="' . Database::escape_string($course_id) . '" ' . $sql_session;
  1610. $rs = Database::query($sql);
  1611. $num = Database::num_rows($rs);
  1612. if ($num == 0) {
  1613. return null;
  1614. }
  1615. $row = Database::fetch_array($rs);
  1616. return $row['document_id'];
  1617. }
  1618. /**
  1619. * allow replace user info in file html
  1620. * @param string The course code
  1621. * @return string The html content of the certificate
  1622. */
  1623. public static function replace_user_info_into_html($user_id, $course_code, $is_preview = false)
  1624. {
  1625. $user_id = intval($user_id);
  1626. $course_info = api_get_course_info($course_code);
  1627. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  1628. $course_id = $course_info['real_id'];
  1629. $document_id = self::get_default_certificate_id($course_code);
  1630. $my_content_html = null;
  1631. if ($document_id) {
  1632. $sql = "SELECT path FROM $tbl_document
  1633. WHERE c_id = $course_id AND id = $document_id";
  1634. $rs = Database::query($sql);
  1635. $new_content = '';
  1636. $all_user_info = array();
  1637. if (Database::num_rows($rs)) {
  1638. $row = Database::fetch_array($rs);
  1639. $filepath = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
  1640. if (is_file($filepath)) {
  1641. $my_content_html = file_get_contents($filepath);
  1642. }
  1643. $all_user_info = self::get_all_info_to_certificate($user_id, $course_code, $is_preview);
  1644. $info_to_be_replaced_in_content_html = $all_user_info[0];
  1645. $info_to_replace_in_content_html = $all_user_info[1];
  1646. $new_content = str_replace(
  1647. $info_to_be_replaced_in_content_html,
  1648. $info_to_replace_in_content_html,
  1649. $my_content_html
  1650. );
  1651. }
  1652. return array('content' => $new_content, 'variables' => $all_user_info);
  1653. }
  1654. return array();
  1655. }
  1656. /**
  1657. * Return all content to replace and all content to be replace
  1658. * @param int $user_id
  1659. * @param int $course_id
  1660. * @param bool $is_preview
  1661. * @return array
  1662. */
  1663. static function get_all_info_to_certificate($user_id, $course_id, $is_preview = false)
  1664. {
  1665. $info_list = array();
  1666. $user_id = intval($user_id);
  1667. $course_info = api_get_course_info($course_id);
  1668. //info portal
  1669. $organization_name = api_get_setting('Institution');
  1670. $portal_name = api_get_setting('siteName');
  1671. //Extra user data information
  1672. $extra_user_info_data = UserManager::get_extra_user_data($user_id, false, false, false, true);
  1673. //Student information
  1674. $user_info = api_get_user_info($user_id);
  1675. $first_name = $user_info['firstname'];
  1676. $last_name = $user_info['lastname'];
  1677. $official_code = $user_info['official_code'];
  1678. //Teacher information
  1679. $info_teacher_id = UserManager::get_user_id_of_course_admin_or_session_admin($course_id);
  1680. $teacher_info = api_get_user_info($info_teacher_id);
  1681. $teacher_first_name = $teacher_info['firstname'];
  1682. $teacher_last_name = $teacher_info['lastname'];
  1683. // info gradebook certificate
  1684. $info_grade_certificate = UserManager::get_info_gradebook_certificate($course_id, $user_id);
  1685. $date_certificate = $info_grade_certificate['created_at'];
  1686. $date_long_certificate = '';
  1687. $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
  1688. if (!empty($date_certificate)) {
  1689. $date_long_certificate = api_convert_and_format_date($date_certificate);
  1690. $date_no_time = api_convert_and_format_date($date_certificate, DATE_FORMAT_LONG_NO_DAY);
  1691. }
  1692. if ($is_preview) {
  1693. $date_long_certificate = api_convert_and_format_date(api_get_utc_datetime());
  1694. $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
  1695. }
  1696. $url = api_get_path(WEB_PATH) . 'certificates/index.php?id=' . $info_grade_certificate['id'];
  1697. //replace content
  1698. $info_to_replace_in_content_html = array($first_name,
  1699. $last_name,
  1700. $organization_name,
  1701. $portal_name,
  1702. $teacher_first_name,
  1703. $teacher_last_name,
  1704. $official_code,
  1705. $date_long_certificate,
  1706. $date_no_time,
  1707. $course_id,
  1708. $course_info['name'],
  1709. $info_grade_certificate['grade'],
  1710. $url,
  1711. '<a href="' . $url . '" target="_blank">' . get_lang('CertificateOnlineLink') . '</a>',
  1712. '((certificate_barcode))',
  1713. );
  1714. $info_to_be_replaced_in_content_html = array('((user_firstname))',
  1715. '((user_lastname))',
  1716. '((gradebook_institution))',
  1717. '((gradebook_sitename))',
  1718. '((teacher_firstname))',
  1719. '((teacher_lastname))',
  1720. '((official_code))',
  1721. '((date_certificate))',
  1722. '((date_certificate_no_time))',
  1723. '((course_code))',
  1724. '((course_title))',
  1725. '((gradebook_grade))',
  1726. '((certificate_link))',
  1727. '((certificate_link_html))',
  1728. '((certificate_barcode))',
  1729. );
  1730. if (!empty($extra_user_info_data)) {
  1731. foreach ($extra_user_info_data as $key_extra => $value_extra) {
  1732. $info_to_be_replaced_in_content_html[] = '((' . strtolower($key_extra) . '))';
  1733. $info_to_replace_in_content_html[] = $value_extra;
  1734. }
  1735. }
  1736. $info_list[] = $info_to_be_replaced_in_content_html;
  1737. $info_list[] = $info_to_replace_in_content_html;
  1738. return $info_list;
  1739. }
  1740. /**
  1741. * Remove default certificate
  1742. * @param string $course_id The course code
  1743. * @param int $default_certificate_id The document id of the default certificate
  1744. * @return void()
  1745. */
  1746. public static function remove_attach_certificate($course_id, $default_certificate_id)
  1747. {
  1748. if (empty($default_certificate_id)) {
  1749. return false;
  1750. }
  1751. $default_certificate = self::get_default_certificate_id($course_id);
  1752. if ((int) $default_certificate == (int) $default_certificate_id) {
  1753. $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1754. $session_id = api_get_session_id();
  1755. if ($session_id == 0 || is_null($session_id)) {
  1756. $sql_session = 'AND (session_id=' . intval($session_id) . ' OR isnull(session_id)) ';
  1757. } elseif ($session_id > 0) {
  1758. $sql_session = 'AND session_id=' . intval($session_id);
  1759. } else {
  1760. $sql_session = '';
  1761. }
  1762. $sql = 'UPDATE ' . $tbl_category . ' SET document_id=null
  1763. WHERE
  1764. course_code = "' . Database::escape_string($course_id) . '" AND
  1765. document_id="' . $default_certificate_id . '" ' . $sql_session;
  1766. Database::query($sql);
  1767. }
  1768. }
  1769. /**
  1770. * Create directory certificate
  1771. * @param string $courseCode
  1772. * @return void()
  1773. */
  1774. public static function create_directory_certificate_in_course($courseCode)
  1775. {
  1776. $courseInfo = api_get_course_info($courseCode);
  1777. if (!empty($courseInfo)) {
  1778. $to_group_id = 0;
  1779. $to_user_id = null;
  1780. $course_dir = $courseInfo['path'] . "/document/";
  1781. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  1782. $base_work_dir = $sys_course_path . $course_dir;
  1783. $base_work_dir_test = $base_work_dir . 'certificates';
  1784. $dir_name = '/certificates';
  1785. $post_dir_name = get_lang('CertificatesFiles');
  1786. $visibility_command = 'invisible';
  1787. $id = self::get_document_id_of_directory_certificate();
  1788. if (empty($id)) {
  1789. create_unexisting_directory(
  1790. $courseInfo,
  1791. api_get_user_id(),
  1792. api_get_session_id(),
  1793. $to_group_id,
  1794. $to_user_id,
  1795. $base_work_dir,
  1796. $dir_name,
  1797. $post_dir_name,
  1798. null,
  1799. false
  1800. );
  1801. $id = self::get_document_id_of_directory_certificate();
  1802. if (empty($id)) {
  1803. $id = add_document(
  1804. $courseInfo,
  1805. $dir_name,
  1806. 'folder',
  1807. 0,
  1808. $post_dir_name,
  1809. null,
  1810. 0,
  1811. true,
  1812. $to_group_id
  1813. );
  1814. }
  1815. if (!empty($id)) {
  1816. api_item_property_update(
  1817. $courseInfo,
  1818. TOOL_DOCUMENT,
  1819. $id,
  1820. $visibility_command,
  1821. api_get_user_id()
  1822. );
  1823. }
  1824. }
  1825. }
  1826. }
  1827. /**
  1828. * Get the document id of the directory certificate
  1829. * @return int The document id of the directory certificate
  1830. */
  1831. public static function get_document_id_of_directory_certificate()
  1832. {
  1833. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  1834. $course_id = api_get_course_int_id();
  1835. $sql = "SELECT id FROM $tbl_document WHERE c_id = $course_id AND path='/certificates' ";
  1836. $rs = Database::query($sql);
  1837. $row = Database::fetch_array($rs);
  1838. return $row['id'];
  1839. }
  1840. /**
  1841. * Check if a directory given is for certificate
  1842. * @param string $dir path of directory
  1843. * @return bool true if is a certificate or false otherwise
  1844. */
  1845. public static function is_certificate_mode($dir)
  1846. {
  1847. // I'm in the certification module?
  1848. $is_certificate_mode = false;
  1849. $is_certificate_array = explode('/', $dir);
  1850. array_shift($is_certificate_array);
  1851. if (isset($is_certificate_array[0]) && $is_certificate_array[0] == 'certificates') {
  1852. $is_certificate_mode = true;
  1853. }
  1854. return $is_certificate_mode;
  1855. }
  1856. /**
  1857. * Gets the list of included resources as a list of absolute or relative paths from a html file or string html
  1858. * This allows for a better SCORM export or replace urls inside content html from copy course
  1859. * The list will generally include pictures, flash objects, java applets, or any other
  1860. * stuff included in the source of the current item. The current item is expected
  1861. * to be an HTML file or string html. If it is not, then the function will return and empty list.
  1862. * @param string source html (content or path)
  1863. * @param bool is file or string html
  1864. * @param string type (one of the app tools) - optional (otherwise takes the current item's type)
  1865. * @param int level of recursivity we're in
  1866. * @return array List of file paths. An additional field containing 'local' or 'remote' helps determine
  1867. * if the file should be copied into the zip or just linked
  1868. */
  1869. public static function get_resources_from_source_html($source_html, $is_file = false, $type = null, $recursivity = 1)
  1870. {
  1871. $max = 5;
  1872. $attributes = array();
  1873. $wanted_attributes = array('src', 'url', '@import', 'href', 'value', 'flashvars');
  1874. $explode_attributes = array('flashvars' => 'file');
  1875. $abs_path = '';
  1876. if ($recursivity > $max) {
  1877. return array();
  1878. }
  1879. if (!isset($type)) {
  1880. $type = TOOL_DOCUMENT;
  1881. }
  1882. if (!$is_file) {
  1883. $attributes = self::parse_HTML_attributes($source_html, $wanted_attributes, $explode_attributes);
  1884. } else {
  1885. if (is_file($source_html)) {
  1886. $abs_path = $source_html;
  1887. //for now, read the whole file in one go (that's gonna be a problem when the file is too big)
  1888. $info = pathinfo($abs_path);
  1889. $ext = $info['extension'];
  1890. switch (strtolower($ext)) {
  1891. case 'html' :
  1892. case 'htm' :
  1893. case 'shtml':
  1894. case 'css' :
  1895. $file_content = file_get_contents($abs_path);
  1896. //get an array of attributes from the HTML source
  1897. $attributes = self::parse_HTML_attributes($file_content, $wanted_attributes, $explode_attributes);
  1898. break;
  1899. default :
  1900. break;
  1901. }
  1902. } else {
  1903. return false;
  1904. }
  1905. }
  1906. $files_list = array();
  1907. switch ($type) {
  1908. case TOOL_DOCUMENT :
  1909. case TOOL_QUIZ:
  1910. case 'sco':
  1911. foreach ($wanted_attributes as $attr) {
  1912. if (isset($attributes[$attr])) {
  1913. //find which kind of path these are (local or remote)
  1914. $sources = $attributes[$attr];
  1915. foreach ($sources as $source) {
  1916. //skip what is obviously not a resource
  1917. if (strpos($source, '+this.'))
  1918. continue; //javascript code - will still work unaltered
  1919. if (strpos($source, '.') === false)
  1920. continue; //no dot, should not be an external file anyway
  1921. if (strpos($source, 'mailto:'))
  1922. continue; //mailto link
  1923. if (strpos($source, ';') && !strpos($source, '&amp;'))
  1924. continue; //avoid code - that should help
  1925. if ($attr == 'value') {
  1926. if (strpos($source, 'mp3file')) {
  1927. $files_list[] = array(substr($source, 0, strpos($source, '.swf') + 4), 'local', 'abs');
  1928. $mp3file = substr($source, strpos($source, 'mp3file=') + 8);
  1929. if (substr($mp3file, 0, 1) == '/') {
  1930. $files_list[] = array($mp3file, 'local', 'abs');
  1931. } else {
  1932. $files_list[] = array($mp3file, 'local', 'rel');
  1933. }
  1934. } elseif (strpos($source, 'flv=') === 0) {
  1935. $source = substr($source, 4);
  1936. if (strpos($source, '&') > 0) {
  1937. $source = substr($source, 0, strpos($source, '&'));
  1938. }
  1939. if (strpos($source, '://') > 0) {
  1940. if (strpos($source, api_get_path(WEB_PATH)) !== false) {
  1941. //we found the current portal url
  1942. $files_list[] = array($source, 'local', 'url');
  1943. } else {
  1944. //we didn't find any trace of current portal
  1945. $files_list[] = array($source, 'remote', 'url');
  1946. }
  1947. } else {
  1948. $files_list[] = array($source, 'local', 'abs');
  1949. }
  1950. /* skipping anything else to avoid two entries
  1951. (while the others can have sub-files in their url, flv's can't)*/
  1952. continue;
  1953. }
  1954. }
  1955. if (strpos($source, '://') > 0) {
  1956. //cut at '?' in a URL with params
  1957. if (strpos($source, '?') > 0) {
  1958. $second_part = substr($source, strpos($source, '?'));
  1959. if (strpos($second_part, '://') > 0) {
  1960. //if the second part of the url contains a url too, treat the second one before cutting
  1961. $pos1 = strpos($second_part, '=');
  1962. $pos2 = strpos($second_part, '&');
  1963. $second_part = substr($second_part, $pos1 + 1, $pos2 - ($pos1 + 1));
  1964. if (strpos($second_part, api_get_path(WEB_PATH)) !== false) {
  1965. //we found the current portal url
  1966. $files_list[] = array($second_part, 'local', 'url');
  1967. $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
  1968. if (count($in_files_list) > 0) {
  1969. $files_list = array_merge($files_list, $in_files_list);
  1970. }
  1971. } else {
  1972. //we didn't find any trace of current portal
  1973. $files_list[] = array($second_part, 'remote', 'url');
  1974. }
  1975. } elseif (strpos($second_part, '=') > 0) {
  1976. if (substr($second_part, 0, 1) === '/') {
  1977. //link starts with a /, making it absolute (relative to DocumentRoot)
  1978. $files_list[] = array($second_part, 'local', 'abs');
  1979. $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
  1980. if (count($in_files_list) > 0) {
  1981. $files_list = array_merge($files_list, $in_files_list);
  1982. }
  1983. } elseif (strstr($second_part, '..') === 0) {
  1984. //link is relative but going back in the hierarchy
  1985. $files_list[] = array($second_part, 'local', 'rel');
  1986. //$dir = api_get_path(SYS_CODE_PATH);//dirname($abs_path);
  1987. //$new_abs_path = realpath($dir.'/'.$second_part);
  1988. $dir = '';
  1989. if (!empty($abs_path)) {
  1990. $dir = dirname($abs_path) . '/';
  1991. }
  1992. $new_abs_path = realpath($dir . $second_part);
  1993. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  1994. if (count($in_files_list) > 0) {
  1995. $files_list = array_merge($files_list, $in_files_list);
  1996. }
  1997. } else {
  1998. //no starting '/', making it relative to current document's path
  1999. if (substr($second_part, 0, 2) == './') {
  2000. $second_part = substr($second_part, 2);
  2001. }
  2002. $files_list[] = array($second_part, 'local', 'rel');
  2003. $dir = '';
  2004. if (!empty($abs_path)) {
  2005. $dir = dirname($abs_path) . '/';
  2006. }
  2007. $new_abs_path = realpath($dir . $second_part);
  2008. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2009. if (count($in_files_list) > 0) {
  2010. $files_list = array_merge($files_list, $in_files_list);
  2011. }
  2012. }
  2013. }
  2014. //leave that second part behind now
  2015. $source = substr($source, 0, strpos($source, '?'));
  2016. if (strpos($source, '://') > 0) {
  2017. if (strpos($source, api_get_path(WEB_PATH)) !== false) {
  2018. //we found the current portal url
  2019. $files_list[] = array($source, 'local', 'url');
  2020. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  2021. if (count($in_files_list) > 0) {
  2022. $files_list = array_merge($files_list, $in_files_list);
  2023. }
  2024. } else {
  2025. //we didn't find any trace of current portal
  2026. $files_list[] = array($source, 'remote', 'url');
  2027. }
  2028. } else {
  2029. //no protocol found, make link local
  2030. if (substr($source, 0, 1) === '/') {
  2031. //link starts with a /, making it absolute (relative to DocumentRoot)
  2032. $files_list[] = array($source, 'local', 'abs');
  2033. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  2034. if (count($in_files_list) > 0) {
  2035. $files_list = array_merge($files_list, $in_files_list);
  2036. }
  2037. } elseif (strstr($source, '..') === 0) { //link is relative but going back in the hierarchy
  2038. $files_list[] = array($source, 'local', 'rel');
  2039. $dir = '';
  2040. if (!empty($abs_path)) {
  2041. $dir = dirname($abs_path) . '/';
  2042. }
  2043. $new_abs_path = realpath($dir . $source);
  2044. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2045. if (count($in_files_list) > 0) {
  2046. $files_list = array_merge($files_list, $in_files_list);
  2047. }
  2048. } else {
  2049. //no starting '/', making it relative to current document's path
  2050. if (substr($source, 0, 2) == './') {
  2051. $source = substr($source, 2);
  2052. }
  2053. $files_list[] = array($source, 'local', 'rel');
  2054. $dir = '';
  2055. if (!empty($abs_path)) {
  2056. $dir = dirname($abs_path) . '/';
  2057. }
  2058. $new_abs_path = realpath($dir . $source);
  2059. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2060. if (count($in_files_list) > 0) {
  2061. $files_list = array_merge($files_list, $in_files_list);
  2062. }
  2063. }
  2064. }
  2065. }
  2066. //found some protocol there
  2067. if (strpos($source, api_get_path(WEB_PATH)) !== false) {
  2068. //we found the current portal url
  2069. $files_list[] = array($source, 'local', 'url');
  2070. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  2071. if (count($in_files_list) > 0) {
  2072. $files_list = array_merge($files_list, $in_files_list);
  2073. }
  2074. } else {
  2075. //we didn't find any trace of current portal
  2076. $files_list[] = array($source, 'remote', 'url');
  2077. }
  2078. } else {
  2079. //no protocol found, make link local
  2080. if (substr($source, 0, 1) === '/') {
  2081. //link starts with a /, making it absolute (relative to DocumentRoot)
  2082. $files_list[] = array($source, 'local', 'abs');
  2083. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  2084. if (count($in_files_list) > 0) {
  2085. $files_list = array_merge($files_list, $in_files_list);
  2086. }
  2087. } elseif (strpos($source, '..') === 0) {
  2088. //link is relative but going back in the hierarchy
  2089. $files_list[] = array($source, 'local', 'rel');
  2090. $dir = '';
  2091. if (!empty($abs_path)) {
  2092. $dir = dirname($abs_path) . '/';
  2093. }
  2094. $new_abs_path = realpath($dir . $source);
  2095. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2096. if (count($in_files_list) > 0) {
  2097. $files_list = array_merge($files_list, $in_files_list);
  2098. }
  2099. } else {
  2100. //no starting '/', making it relative to current document's path
  2101. if (substr($source, 0, 2) == './') {
  2102. $source = substr($source, 2);
  2103. }
  2104. $files_list[] = array($source, 'local', 'rel');
  2105. $dir = '';
  2106. if (!empty($abs_path)) {
  2107. $dir = dirname($abs_path) . '/';
  2108. }
  2109. $new_abs_path = realpath($dir . $source);
  2110. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  2111. if (count($in_files_list) > 0) {
  2112. $files_list = array_merge($files_list, $in_files_list);
  2113. }
  2114. }
  2115. }
  2116. }
  2117. }
  2118. }
  2119. break;
  2120. default: //ignore
  2121. break;
  2122. }
  2123. $checked_files_list = array();
  2124. $checked_array_list = array();
  2125. if (count($files_list) > 0) {
  2126. foreach ($files_list as $idx => $file) {
  2127. if (!empty($file[0])) {
  2128. if (!in_array($file[0], $checked_files_list)) {
  2129. $checked_files_list[] = $files_list[$idx][0];
  2130. $checked_array_list[] = $files_list[$idx];
  2131. }
  2132. }
  2133. }
  2134. }
  2135. return $checked_array_list;
  2136. }
  2137. /**
  2138. * Parses the HTML attributes given as string.
  2139. *
  2140. * @param string HTML attribute string
  2141. * @param array List of attributes that we want to get back
  2142. * @param array
  2143. * @return array An associative array of attributes
  2144. * @author Based on a function from the HTML_Common2 PEAR module *
  2145. */
  2146. public static function parse_HTML_attributes($attrString, $wanted = array(), $explode_variables = array())
  2147. {
  2148. $attributes = array();
  2149. $regs = array();
  2150. $reduced = false;
  2151. if (count($wanted) > 0) {
  2152. $reduced = true;
  2153. }
  2154. try {
  2155. //Find all occurences of something that looks like a URL
  2156. // The structure of this regexp is:
  2157. // (find protocol) then
  2158. // (optionally find some kind of space 1 or more times) then
  2159. // find (either an equal sign or a bracket) followed by an optional space
  2160. // followed by some text without quotes (between quotes itself or not)
  2161. // then possible closing brackets if we were in the opening bracket case
  2162. // OR something like @import()
  2163. $res = preg_match_all(
  2164. '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]*))' .
  2165. // '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]|[^\x00-\x7F])*)' . -> seems to be taking too much
  2166. // '/(((([A-Za-z_:])([^\x00-\x7F])*)' . -> takes only last letter of parameter name
  2167. '([ \n\t\r]+)?(' .
  2168. // '(=([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+))' . -> doesn't restrict close enough to the url itself
  2169. '(=([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+))' .
  2170. '|' .
  2171. // '(\(([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)\))' . -> doesn't restrict close enough to the url itself
  2172. '(\(([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+)\))' .
  2173. '))' .
  2174. '|' .
  2175. // '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))?/', -> takes a lot (like 100's of thousands of empty possibilities)
  2176. '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))/',
  2177. $attrString,
  2178. $regs
  2179. );
  2180. } catch (Exception $e) {
  2181. error_log('Caught exception: ' . $e->getMessage(), 0);
  2182. }
  2183. if ($res) {
  2184. for ($i = 0; $i < count($regs[1]); $i++) {
  2185. $name = trim($regs[3][$i]);
  2186. $check = trim($regs[0][$i]);
  2187. $value = trim($regs[10][$i]);
  2188. if (empty($value) and !empty($regs[13][$i])) {
  2189. $value = $regs[13][$i];
  2190. }
  2191. if (empty($name) && !empty($regs[16][$i])) {
  2192. $name = '@import';
  2193. $value = trim($regs[16][$i]);
  2194. }
  2195. if (!empty($name)) {
  2196. if (!$reduced OR in_array(strtolower($name), $wanted)) {
  2197. if ($name == $check) {
  2198. $attributes[strtolower($name)][] = strtolower($name);
  2199. } else {
  2200. if (!empty($value) && ($value[0] == '\'' || $value[0] == '"')) {
  2201. $value = substr($value, 1, -1);
  2202. }
  2203. if ($value == 'API.LMSGetValue(name') {
  2204. $value = 'API.LMSGetValue(name)';
  2205. }
  2206. //Gets the xx.flv value from the string flashvars="width=320&height=240&autostart=false&file=xxx.flv&repeat=false"
  2207. if (isset($explode_variables[$name])) {
  2208. $value_modified = str_replace('&amp;', '&', $value);
  2209. $value_array = explode('&', $value_modified);
  2210. foreach ($value_array as $item) {
  2211. list($key, $item_value) = explode('=', $item);
  2212. if ($key == $explode_variables[$name]) {
  2213. $attributes[strtolower($name)][] = $item_value;
  2214. }
  2215. }
  2216. }
  2217. $attributes[strtolower($name)][] = $value;
  2218. }
  2219. }
  2220. }
  2221. }
  2222. }
  2223. return $attributes;
  2224. }
  2225. /**
  2226. * Replace urls inside content html from a copy course
  2227. * @param string $content_html
  2228. * @param string $origin_course_code
  2229. * @param string $destination_course_directory
  2230. * @param string $origin_course_path_from_zip
  2231. * @param string $origin_course_info_path
  2232. *
  2233. * @return string new content html with replaced urls or return false if content is not a string
  2234. */
  2235. static function replace_urls_inside_content_html_from_copy_course(
  2236. $content_html,
  2237. $origin_course_code,
  2238. $destination_course_directory,
  2239. $origin_course_path_from_zip = null,
  2240. $origin_course_info_path = null
  2241. ) {
  2242. require_once api_get_path(LIBRARY_PATH) . 'fileUpload.lib.php';
  2243. if (empty($content_html)) {
  2244. return false;
  2245. }
  2246. $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
  2247. $orig_course_info = api_get_course_info($origin_course_code);
  2248. // Course does not exist in the current DB probably this came from a zip file?
  2249. if (empty($orig_course_info)) {
  2250. if (!empty($origin_course_path_from_zip)) {
  2251. $orig_course_path = $origin_course_path_from_zip.'/';
  2252. $orig_course_info_path = $origin_course_info_path;
  2253. }
  2254. } else {
  2255. $orig_course_path = api_get_path(SYS_PATH).'courses/'.$orig_course_info['path'] . '/';
  2256. $orig_course_info_path = $orig_course_info['path'];
  2257. }
  2258. $destination_course_code = CourseManager::get_course_id_from_path($destination_course_directory);
  2259. $destination_course_info = api_get_course_info($destination_course_code);
  2260. $dest_course_path = api_get_path(SYS_COURSE_PATH) . $destination_course_directory . '/';
  2261. $dest_course_path_rel = api_get_path(REL_COURSE_PATH) . $destination_course_directory . '/';
  2262. $user_id = api_get_user_id();
  2263. if (!empty($orig_source_html)) {
  2264. foreach ($orig_source_html as $source) {
  2265. // Get information about source url
  2266. $real_orig_url = $source[0]; // url
  2267. $scope_url = $source[1]; // scope (local, remote)
  2268. $type_url = $source[2]; // type (rel, abs, url)
  2269. // Get path and query from origin url
  2270. $orig_parse_url = parse_url($real_orig_url);
  2271. $real_orig_path = isset($orig_parse_url['path']) ? $orig_parse_url['path'] : null;
  2272. $real_orig_query = isset($orig_parse_url['query']) ? $orig_parse_url['query'] : null;
  2273. // Replace origin course code by destination course code from origin url query
  2274. $dest_url_query = '';
  2275. if (!empty($real_orig_query)) {
  2276. $dest_url_query = '?' . $real_orig_query;
  2277. if (strpos($dest_url_query, $origin_course_code) !== false) {
  2278. $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
  2279. }
  2280. }
  2281. if ($scope_url == 'local') {
  2282. if ($type_url == 'abs' || $type_url == 'rel') {
  2283. $document_file = strstr($real_orig_path, 'document');
  2284. if (strpos($real_orig_path, $document_file) !== false) {
  2285. $origin_filepath = $orig_course_path.$document_file;
  2286. $destination_filepath = $dest_course_path.$document_file;
  2287. // copy origin file inside destination course
  2288. if (file_exists($origin_filepath)) {
  2289. $filepath_dir = dirname($destination_filepath);
  2290. if (!is_dir($filepath_dir)) {
  2291. $perm = api_get_permissions_for_new_directories();
  2292. $result = @mkdir($filepath_dir, $perm, true);
  2293. if ($result) {
  2294. $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $filepath_dir);
  2295. //Add to item properties to the new folder
  2296. $doc_id = add_document(
  2297. $destination_course_info,
  2298. $filepath_to_add,
  2299. 'folder',
  2300. 0,
  2301. basename($filepath_to_add)
  2302. );
  2303. api_item_property_update(
  2304. $destination_course_info,
  2305. TOOL_DOCUMENT,
  2306. $doc_id,
  2307. 'FolderCreated',
  2308. $user_id,
  2309. null,
  2310. null,
  2311. null,
  2312. null
  2313. );
  2314. }
  2315. }
  2316. if (!file_exists($destination_filepath)) {
  2317. $result = @copy($origin_filepath, $destination_filepath);
  2318. if ($result) {
  2319. $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $destination_filepath);
  2320. $size = filesize($destination_filepath);
  2321. // Add to item properties to the file
  2322. $doc_id = add_document(
  2323. $destination_course_info,
  2324. $filepath_to_add,
  2325. 'file',
  2326. $size,
  2327. basename($filepath_to_add)
  2328. );
  2329. api_item_property_update(
  2330. $destination_course_info,
  2331. TOOL_DOCUMENT,
  2332. $doc_id,
  2333. 'FolderCreated',
  2334. $user_id,
  2335. null,
  2336. null,
  2337. null,
  2338. null
  2339. );
  2340. }
  2341. }
  2342. }
  2343. // Replace origin course path by destination course path.
  2344. if (strpos($content_html, $real_orig_url) !== false) {
  2345. $url_course_path = str_replace($orig_course_info_path.'/'.$document_file, '', $real_orig_path);
  2346. //var_dump($dest_course_path_rel);
  2347. //$destination_url = $url_course_path . $destination_course_directory . '/' . $document_file . $dest_url_query;
  2348. // See BT#7780
  2349. $destination_url = $dest_course_path_rel . $document_file . $dest_url_query;
  2350. // If the course code doesn't exist in the path? what we do? Nothing! see BT#1985
  2351. if (strpos($real_orig_path, $origin_course_code) === false) {
  2352. $url_course_path = $real_orig_path;
  2353. $destination_url = $real_orig_path;
  2354. }
  2355. $content_html = str_replace($real_orig_url, $destination_url, $content_html);
  2356. }
  2357. }
  2358. // replace origin course code by destination course code from origin url
  2359. if (strpos($real_orig_url, '?') === 0) {
  2360. $dest_url = str_replace($origin_course_code, $destination_course_code, $real_orig_url);
  2361. $content_html = str_replace($real_orig_url, $dest_url, $content_html);
  2362. }
  2363. }
  2364. }
  2365. }
  2366. }
  2367. return $content_html;
  2368. }
  2369. /**
  2370. * Replace urls inside content html when moving a file
  2371. * @todo this code is only called in document.php but is commented
  2372. * @param string content html
  2373. * @param string origin
  2374. * @param string destination
  2375. * @return string new content html with replaced urls or return false if content is not a string
  2376. */
  2377. function replace_urls_inside_content_html_when_moving_file($file_name, $original_path, $destiny_path)
  2378. {
  2379. if (substr($original_path, strlen($original_path) - 1, strlen($original_path)) == '/') {
  2380. $original = $original_path . $file_name;
  2381. } else {
  2382. $original = $original_path . '/' . $file_name;
  2383. }
  2384. if (substr($destiny_path, strlen($destiny_path) - 1, strlen($destiny_path)) == '/') {
  2385. $destination = $destiny_path . $file_name;
  2386. } else {
  2387. $destination = $destiny_path . '/' . $file_name;
  2388. }
  2389. $original_count = count(explode('/', $original));
  2390. $destination_count = count(explode('/', $destination));
  2391. if ($original_count == $destination_count) {
  2392. //Nothing to change
  2393. return true;
  2394. }
  2395. if ($original_count > $destination_count) {
  2396. $mode = 'outside';
  2397. } else {
  2398. $mode = 'inside';
  2399. }
  2400. //We do not select the $original_path becayse the file was already moved
  2401. $content_html = file_get_contents($destiny_path . '/' . $file_name);
  2402. $destination_file = $destiny_path . '/' . $file_name;
  2403. $pre_original = strstr($original_path, 'document');
  2404. $pre_destin = strstr($destiny_path, 'document');
  2405. $pre_original = substr($pre_original, 8, strlen($pre_original));
  2406. $pre_destin = substr($pre_destin, 8, strlen($pre_destin));
  2407. $levels = count(explode('/', $pre_destin)) - 1;
  2408. $link_to_add = '';
  2409. for ($i = 1; $i <= $levels; $i++) {
  2410. $link_to_add .= '../';
  2411. }
  2412. if ($pre_original == '/') {
  2413. $pre_original = '';
  2414. }
  2415. if ($pre_destin == '/') {
  2416. $pre_destin = '';
  2417. }
  2418. if ($pre_original != '') {
  2419. $pre_original = '..' . $pre_original . '/';
  2420. }
  2421. if ($pre_destin != '') {
  2422. $pre_destin = '..' . $pre_destin . '/';
  2423. }
  2424. $levels = explode('/', $pre_original);
  2425. $count_pre_destination_levels = 0;
  2426. foreach ($levels as $item) {
  2427. if (!empty($item) && $item != '..') {
  2428. $count_pre_destination_levels++;
  2429. }
  2430. }
  2431. $count_pre_destination_levels--;
  2432. //$count_pre_destination_levels = count() - 3;
  2433. if ($count_pre_destination_levels == 0) {
  2434. $count_pre_destination_levels = 1;
  2435. }
  2436. //echo '$count_pre_destination_levels '. $count_pre_destination_levels;
  2437. $pre_remove = '';
  2438. for ($i = 1; $i <= $count_pre_destination_levels; $i++) {
  2439. $pre_remove .='..\/';
  2440. }
  2441. $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
  2442. foreach ($orig_source_html as $source) {
  2443. // get information about source url
  2444. $real_orig_url = $source[0]; // url
  2445. $scope_url = $source[1]; // scope (local, remote)
  2446. $type_url = $source[2]; // tyle (rel, abs, url)
  2447. // Get path and query from origin url
  2448. $orig_parse_url = parse_url($real_orig_url);
  2449. $real_orig_path = $orig_parse_url['path'];
  2450. $real_orig_query = $orig_parse_url['query'];
  2451. // Replace origin course code by destination course code from origin url query
  2452. /*
  2453. $dest_url_query = '';
  2454. if (!empty($real_orig_query)) {
  2455. $dest_url_query = '?'.$real_orig_query;
  2456. if (strpos($dest_url_query,$origin_course_code) !== false) {
  2457. $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
  2458. }
  2459. } */
  2460. if ($scope_url == 'local') {
  2461. if ($type_url == 'abs' || $type_url == 'rel') {
  2462. $document_file = strstr($real_orig_path, 'document');
  2463. if (strpos($real_orig_path, $document_file) !== false) {
  2464. echo 'continue1';
  2465. continue;
  2466. } else {
  2467. $real_orig_url_temp = '';
  2468. if ($mode == 'inside') {
  2469. $real_orig_url_temp = str_replace('../', '', $real_orig_url);
  2470. $destination_url = $link_to_add . $real_orig_url_temp;
  2471. } else {
  2472. $real_orig_url_temp = $real_orig_url;
  2473. $destination_url = preg_replace("/" . $pre_remove . "/", '', $real_orig_url, 1);
  2474. }
  2475. if ($real_orig_url == $destination_url) {
  2476. //echo 'continue2';
  2477. continue;
  2478. }
  2479. $content_html = str_replace($real_orig_url, $destination_url, $content_html);
  2480. }
  2481. } else {
  2482. echo 'continue3';
  2483. continue;
  2484. }
  2485. }
  2486. }
  2487. $return = file_put_contents($destination, $content_html);
  2488. return $return;
  2489. }
  2490. /**
  2491. * @param int $document_id
  2492. * @param string $course_code
  2493. */
  2494. public static function export_to_pdf($document_id, $course_code)
  2495. {
  2496. require_once api_get_path(LIBRARY_PATH) . 'pdf.lib.php';
  2497. $course_data = api_get_course_info($course_code);
  2498. $document_data = self::get_document_data_by_id($document_id, $course_code);
  2499. $file_path = api_get_path(SYS_COURSE_PATH) . $course_data['path'] . '/document' . $document_data['path'];
  2500. $pdf = new PDF();
  2501. $pdf->html_to_pdf($file_path, $document_data['title'], $course_code);
  2502. }
  2503. /**
  2504. * Uploads a document
  2505. *
  2506. * @param array $files the $_FILES variable
  2507. * @param string $path
  2508. * @param string $title
  2509. * @param string $comment
  2510. * @param int $unzip unzip or not the file
  2511. * @param string $if_exists overwrite, rename or warn (default)
  2512. * @param bool $index_document index document (search xapian module)
  2513. * @param bool $show_output print html messages
  2514. * @return array|bool
  2515. */
  2516. public static function upload_document(
  2517. $files,
  2518. $path,
  2519. $title = null,
  2520. $comment = null,
  2521. $unzip = 0,
  2522. $if_exists = null,
  2523. $index_document = false,
  2524. $show_output = false
  2525. ) {
  2526. require_once api_get_path(LIBRARY_PATH) . 'fileUpload.lib.php';
  2527. $course_info = api_get_course_info();
  2528. $sessionId = api_get_session_id();
  2529. $course_dir = $course_info['path'] . '/document';
  2530. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  2531. $base_work_dir = $sys_course_path . $course_dir;
  2532. if (isset($files['file'])) {
  2533. $upload_ok = process_uploaded_file($files['file'], $show_output);
  2534. if ($upload_ok) {
  2535. // File got on the server without problems, now process it
  2536. $new_path = handle_uploaded_document(
  2537. $course_info,
  2538. $files['file'],
  2539. $base_work_dir,
  2540. $path,
  2541. api_get_user_id(),
  2542. api_get_group_id(),
  2543. null,
  2544. $unzip,
  2545. $if_exists,
  2546. $show_output,
  2547. false,
  2548. null,
  2549. $sessionId
  2550. );
  2551. if ($new_path) {
  2552. $documentId = DocumentManager::get_document_id(
  2553. $course_info,
  2554. $new_path,
  2555. $sessionId
  2556. );
  2557. if (!empty($documentId)) {
  2558. $table_document = Database::get_course_table(TABLE_DOCUMENT);
  2559. $params = array();
  2560. /*if ($if_exists == 'rename') {
  2561. // Remove prefix
  2562. $suffix = DocumentManager::getDocumentSuffix(
  2563. $course_info,
  2564. $sessionId,
  2565. api_get_group_id()
  2566. );
  2567. $new_path = basename($new_path);
  2568. $new_path = str_replace($suffix, '', $new_path);
  2569. error_log('renamed');
  2570. error_log($new_path);
  2571. $params['title'] = get_document_title($new_path);
  2572. } else {
  2573. if (!empty($title)) {
  2574. $params['title'] = get_document_title($title);
  2575. } else {
  2576. $params['title'] = get_document_title($files['file']['name']);
  2577. }
  2578. }*/
  2579. if (!empty($comment)) {
  2580. $params['comment'] = trim($comment);
  2581. }
  2582. Database::update(
  2583. $table_document,
  2584. $params,
  2585. array(
  2586. 'id = ? AND c_id = ? ' => array(
  2587. $documentId,
  2588. $course_info['real_id']
  2589. )
  2590. )
  2591. );
  2592. }
  2593. // Showing message when sending zip files
  2594. if ($new_path === true && $unzip == 1 && $show_output) {
  2595. Display::display_confirmation_message(
  2596. get_lang('UplUploadSucceeded') . '<br />',
  2597. false
  2598. );
  2599. }
  2600. if ($index_document) {
  2601. self::index_document(
  2602. $documentId,
  2603. $course_info['code'],
  2604. null,
  2605. $_POST['language'],
  2606. $_REQUEST,
  2607. $if_exists
  2608. );
  2609. }
  2610. if (!empty($documentId) && is_numeric($documentId)) {
  2611. $documentData = self::get_document_data_by_id(
  2612. $documentId,
  2613. $course_info['code'],
  2614. false,
  2615. $sessionId
  2616. );
  2617. return $documentData;
  2618. }
  2619. }
  2620. }
  2621. }
  2622. return false;
  2623. }
  2624. /**
  2625. * Obtains the text inside the file with the right parser
  2626. */
  2627. public static function get_text_content($doc_path, $doc_mime)
  2628. {
  2629. // TODO: review w$ compatibility
  2630. // Use usual exec output lines array to store stdout instead of a temp file
  2631. // because we need to store it at RAM anyway before index on ChamiloIndexer object
  2632. $ret_val = null;
  2633. switch ($doc_mime) {
  2634. case 'text/plain':
  2635. $handle = fopen($doc_path, 'r');
  2636. $output = array(fread($handle, filesize($doc_path)));
  2637. fclose($handle);
  2638. break;
  2639. case 'application/pdf':
  2640. exec("pdftotext $doc_path -", $output, $ret_val);
  2641. break;
  2642. case 'application/postscript':
  2643. $temp_file = tempnam(sys_get_temp_dir(), 'chamilo');
  2644. exec("ps2pdf $doc_path $temp_file", $output, $ret_val);
  2645. if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
  2646. return false;
  2647. }
  2648. exec("pdftotext $temp_file -", $output, $ret_val);
  2649. unlink($temp_file);
  2650. break;
  2651. case 'application/msword':
  2652. exec("catdoc $doc_path", $output, $ret_val);
  2653. break;
  2654. case 'text/html':
  2655. exec("html2text $doc_path", $output, $ret_val);
  2656. break;
  2657. case 'text/rtf':
  2658. // Note: correct handling of code pages in unrtf
  2659. // on debian lenny unrtf v0.19.2 can not, but unrtf v0.20.5 can
  2660. exec("unrtf --text $doc_path", $output, $ret_val);
  2661. if ($ret_val == 127) { // command not found
  2662. return false;
  2663. }
  2664. // Avoid index unrtf comments
  2665. if (is_array($output) && count($output) > 1) {
  2666. $parsed_output = array();
  2667. foreach ($output as & $line) {
  2668. if (!preg_match('/^###/', $line, $matches)) {
  2669. if (!empty($line)) {
  2670. $parsed_output[] = $line;
  2671. }
  2672. }
  2673. }
  2674. $output = $parsed_output;
  2675. }
  2676. break;
  2677. case 'application/vnd.ms-powerpoint':
  2678. exec("catppt $doc_path", $output, $ret_val);
  2679. break;
  2680. case 'application/vnd.ms-excel':
  2681. exec("xls2csv -c\" \" $doc_path", $output, $ret_val);
  2682. break;
  2683. }
  2684. $content = '';
  2685. if (!is_null($ret_val)) {
  2686. if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
  2687. return false;
  2688. }
  2689. }
  2690. if (isset($output)) {
  2691. foreach ($output as & $line) {
  2692. $content .= $line . "\n";
  2693. }
  2694. return $content;
  2695. } else {
  2696. return false;
  2697. }
  2698. }
  2699. /**
  2700. * Calculates the total size of all documents in a course
  2701. *
  2702. * @author Bert vanderkimpen
  2703. * @param int $course_id
  2704. * @param int $group_id (to calculate group document space)
  2705. * @param int $session_id
  2706. *
  2707. * @return int total size
  2708. */
  2709. static function documents_total_space($course_id = null, $group_id = null, $session_id = null)
  2710. {
  2711. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  2712. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  2713. if (isset($course_id)) {
  2714. $course_id = intval($course_id);
  2715. } else {
  2716. $course_id = api_get_course_int_id();
  2717. }
  2718. $group_condition = null;
  2719. if (isset($group_id)) {
  2720. $group_id = intval($group_id);
  2721. $group_condition = " AND props.to_group_id='" . $group_id . "' ";
  2722. }
  2723. $session_condition = null;
  2724. if (isset($session_id)) {
  2725. $session_id = intval($session_id);
  2726. $session_condition = " AND props.id_session='" . $session_id . "' ";
  2727. }
  2728. $sql = "SELECT SUM(size)
  2729. FROM $TABLE_ITEMPROPERTY AS props
  2730. INNER JOIN $TABLE_DOCUMENT AS docs
  2731. ON (docs.id = props.ref AND props.c_id = docs.c_id)
  2732. WHERE
  2733. props.c_id = $course_id AND
  2734. docs.c_id = $course_id AND
  2735. props.tool = '" . TOOL_DOCUMENT . "' AND
  2736. props.visibility <> 2
  2737. $group_condition
  2738. $session_condition
  2739. ";
  2740. $result = Database::query($sql);
  2741. if ($result && Database::num_rows($result) != 0) {
  2742. $row = Database::fetch_row($result);
  2743. return $row[0];
  2744. } else {
  2745. return 0;
  2746. }
  2747. }
  2748. /**
  2749. * Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
  2750. */
  2751. static function display_quota($course_quota, $already_consumed_space)
  2752. {
  2753. $course_quota_m = round($course_quota / 1048576);
  2754. $already_consumed_space_m = round($already_consumed_space / 1048576);
  2755. $message = get_lang('MaximumAllowedQuota') . ' <strong>' . $course_quota_m . ' megabyte</strong>.<br />';
  2756. $message .= get_lang('CourseCurrentlyUses') . ' <strong>' . $already_consumed_space_m . ' megabyte</strong>.<br />';
  2757. $percentage = round(($already_consumed_space / $course_quota * 100), 1);
  2758. $other_percentage = $percentage < 100 ? 100 - $percentage : 0;
  2759. // Decide where to place percentage in graph
  2760. if ($percentage >= 50) {
  2761. $text_in_filled = '&nbsp;' . $other_percentage . '%';
  2762. $text_in_unfilled = '';
  2763. } else {
  2764. $text_in_unfilled = '&nbsp;' . $other_percentage . '%';
  2765. $text_in_filled = '';
  2766. }
  2767. // Decide the background colour of the graph
  2768. if ($percentage < 65) {
  2769. $colour = '#00BB00'; // Safe - green
  2770. } elseif ($percentage < 90) {
  2771. $colour = '#ffd400'; // Filling up - yelloworange
  2772. } else {
  2773. $colour = '#DD0000'; // Full - red
  2774. }
  2775. // This is used for the table width: a table of only 100 pixels looks too small
  2776. $visual_percentage = 4 * $percentage;
  2777. $visual_other_percentage = 4 * $other_percentage;
  2778. $message .= get_lang('PercentageQuotaInUse') . ': <strong>' . $percentage . '%</strong>.<br />' .
  2779. get_lang('PercentageQuotaFree') . ': <strong>' . $other_percentage . '%</strong>.<br />';
  2780. $show_percentage = '&nbsp;' . $percentage . '%';
  2781. $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">' .
  2782. '<div style="width:' . $percentage . '%; background-color: #bbb; border-right:3px groove #bbb; -moz-border-radius:5px;">&nbsp;</div>' .
  2783. '<span style="margin-top: -15px; margin-left:-15px; position: absolute;font-weight:bold;">' . $show_percentage . '</span></div>';
  2784. echo $message;
  2785. }
  2786. /**
  2787. * Display the document quota in a simple way
  2788. *
  2789. * Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
  2790. */
  2791. static function display_simple_quota($course_quota, $already_consumed_space)
  2792. {
  2793. $course_quota_m = round($course_quota / 1048576);
  2794. $already_consumed_space_m = round($already_consumed_space / 1048576, 2);
  2795. $percentage = $already_consumed_space / $course_quota * 100;
  2796. $percentage = round($percentage, 1);
  2797. $message = get_lang('YouAreCurrentlyUsingXOfYourX');
  2798. $message = sprintf($message, $already_consumed_space_m, $percentage . '%', $course_quota_m . ' ');
  2799. echo Display::div($message, array('id' => 'document_quota'));
  2800. }
  2801. /**
  2802. * Checks if there is enough place to add a file on a directory
  2803. * on the base of a maximum directory size allowed
  2804. *
  2805. * @author Bert Vanderkimpen
  2806. * @param int file_size size of the file in byte
  2807. * @param int max_dir_space maximum size
  2808. * @return boolean true if there is enough space, false otherwise
  2809. *
  2810. * @see enough_space() uses documents_total_space() function
  2811. */
  2812. static function enough_space($file_size, $max_dir_space) {
  2813. if ($max_dir_space) {
  2814. $already_filled_space = self::documents_total_space();
  2815. if (($file_size + $already_filled_space) > $max_dir_space) {
  2816. return false;
  2817. }
  2818. }
  2819. return true;
  2820. }
  2821. /**
  2822. * @param array parameters: count, url, extension
  2823. * @return string
  2824. */
  2825. static function generate_jplayer_jquery($params = array())
  2826. {
  2827. $js_path = api_get_path(WEB_LIBRARY_PATH) . 'javascript/';
  2828. $js = ' $("#jquery_jplayer_' . $params['count'] . '").jPlayer({
  2829. ready: function() {
  2830. $(this).jPlayer("setMedia", {
  2831. ' . $params['extension'] . ' : "' . $params['url'] . '"
  2832. });
  2833. },
  2834. play: function() { // To avoid both jPlayers playing together.
  2835. $(this).jPlayer("pauseOthers");
  2836. },
  2837. //errorAlerts: true,
  2838. //warningAlerts: true,
  2839. swfPath: "' . $js_path . 'jquery-jplayer",
  2840. //supplied: "m4a, oga, mp3, ogg, wav",
  2841. supplied: "' . $params['extension'] . '",
  2842. wmode: "window",
  2843. solution: "flash, html", // Do not change this setting
  2844. cssSelectorAncestor: "#jp_container_' . $params['count'] . '",
  2845. }); ' . "\n\n";
  2846. return $js;
  2847. }
  2848. /**
  2849. *
  2850. * Shows a play icon next to the document title in the document list
  2851. * @param int
  2852. * @param string
  2853. * @return string html content
  2854. */
  2855. static function generate_media_preview($i, $type = 'simple')
  2856. {
  2857. $i = intval($i);
  2858. $extra_controls = $progress = '';
  2859. if ($type == 'advanced') {
  2860. $extra_controls = ' <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
  2861. <li><a href="#" class="jp-mute" tabindex="1">mute</a></li>
  2862. <li><a href="#" class="jp-unmute" tabindex="1">unmute</a></li>';
  2863. $progress = '<div class="jp-progress">
  2864. <div class="jp-seek-bar">
  2865. <div class="jp-play-bar"></div>
  2866. </div>
  2867. </div>';
  2868. }
  2869. //Shows only the play button
  2870. $html = '<div id="jquery_jplayer_' . $i . '" class="jp-jplayer"></div>
  2871. <div id="jp_container_' . $i . '" class="jp-audio">
  2872. <div class="jp-type-single">
  2873. <div class="jp-gui jp-interface">
  2874. <ul class="jp-controls">
  2875. <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
  2876. <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
  2877. ' . $extra_controls . '
  2878. </ul>
  2879. ' . $progress . '
  2880. </div>
  2881. </div>
  2882. </div>';
  2883. //<div id="jplayer_inspector_'.$i.'"></div>
  2884. return $html;
  2885. }
  2886. /**
  2887. * @param array $document_data
  2888. * @return string
  2889. */
  2890. static function generate_video_preview($document_data = array())
  2891. {
  2892. $html = '
  2893. <div id="jp_container_1" class="jp-video">
  2894. <div class="jp-type-single">
  2895. <div id="jquery_jplayer_1" class="jp-jplayer"></div>
  2896. <div class="jp-gui">
  2897. <div class="jp-video-play">
  2898. <a href="javascript:;" class="jp-video-play-icon" tabindex="1">play</a>
  2899. </div>
  2900. <div class="jp-interface">
  2901. <div class="jp-progress">
  2902. <div class="jp-seek-bar">
  2903. <div class="jp-play-bar"></div>
  2904. </div>
  2905. </div>
  2906. <div class="jp-current-time"></div>
  2907. <div class="jp-controls-holder">
  2908. <ul class="jp-controls">
  2909. <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
  2910. <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
  2911. <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
  2912. <li><a href="javascript:;" class="jp-mute" tabindex="1" title="mute">mute</a></li>
  2913. <li><a href="javascript:;" class="jp-unmute" tabindex="1" title="unmute">unmute</a></li>
  2914. <li><a href="javascript:;" class="jp-volume-max" tabindex="1" title="max volume">max volume</a></li>
  2915. </ul>
  2916. <div class="jp-volume-bar">
  2917. <div class="jp-volume-bar-value"></div>
  2918. </div>
  2919. <ul class="jp-toggles">
  2920. <li><a href="javascript:;" class="jp-full-screen" tabindex="1" title="full screen">full screen</a></li>
  2921. <li><a href="javascript:;" class="jp-restore-screen" tabindex="1" title="restore screen">restore screen</a></li>
  2922. <li><a href="javascript:;" class="jp-repeat" tabindex="1" title="repeat">repeat</a></li>
  2923. <li><a href="javascript:;" class="jp-repeat-off" tabindex="1" title="repeat off">repeat off</a></li>
  2924. </ul>
  2925. </div>
  2926. <div class="jp-title">
  2927. <ul>
  2928. <li>' . $document_data['title'] . '</li>
  2929. </ul>
  2930. </div>
  2931. </div>
  2932. </div>
  2933. <div class="jp-no-solution">
  2934. <span>' . get_lang('UpdateRequire') . '</span>
  2935. ' . get_lang("ToPlayTheMediaYouWillNeedToUpdateYourBrowserToARecentVersionYouCanAlsoDownloadTheFile") . '
  2936. </div>
  2937. </div>
  2938. </div>';
  2939. return $html;
  2940. }
  2941. /**
  2942. * @param array $course_info
  2943. * @param bool $lp_id
  2944. * @param string $target
  2945. * @param int $session_id
  2946. * @param bool $add_move_button
  2947. * @param string $filter_by_folder
  2948. * @param string $overwrite_url
  2949. * @param bool $showInvisibleFiles
  2950. * @param bool $showOnlyFolders
  2951. * @param int $folderId
  2952. *
  2953. * @return string
  2954. */
  2955. public static function get_document_preview(
  2956. $course_info,
  2957. $lp_id = false,
  2958. $target = '',
  2959. $session_id = 0,
  2960. $add_move_button = false,
  2961. $filter_by_folder = null,
  2962. $overwrite_url = null,
  2963. $showInvisibleFiles = false,
  2964. $showOnlyFolders = false,
  2965. $folderId = false
  2966. ) {
  2967. if (empty($course_info['real_id']) || empty($course_info['code']) || !is_array($course_info)) {
  2968. return '';
  2969. }
  2970. $overwrite_url = Security::remove_XSS($overwrite_url);
  2971. $user_id = api_get_user_id();
  2972. $user_in_course = false;
  2973. if (api_is_platform_admin()) {
  2974. $user_in_course = true;
  2975. }
  2976. if (!$user_in_course) {
  2977. if (CourseManager::is_course_teacher($user_id, $course_info['code'])) {
  2978. $user_in_course = true;
  2979. }
  2980. }
  2981. // Condition for the session
  2982. $session_id = intval($session_id);
  2983. if (!$user_in_course) {
  2984. if (empty($session_id)) {
  2985. if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) {
  2986. $user_in_course = true;
  2987. }
  2988. // Check if course is open then we can consider that the student is registered to the course
  2989. if (isset($course_info) && in_array($course_info['visibility'], array(2, 3))) {
  2990. $user_in_course = true;
  2991. }
  2992. } else {
  2993. $user_status = SessionManager::get_user_status_in_course_session($user_id, $course_info['code'], $session_id);
  2994. //is true if is an student, course session teacher or coach
  2995. if (in_array($user_status, array('0', '2', '6'))) {
  2996. $user_in_course = true;
  2997. }
  2998. }
  2999. }
  3000. $tbl_doc = Database::get_course_table(TABLE_DOCUMENT);
  3001. $tbl_item_prop = Database::get_course_table(TABLE_ITEM_PROPERTY);
  3002. $condition_session = " AND (id_session = '$session_id' OR id_session = '0' )";
  3003. $add_folder_filter = null;
  3004. if (!empty($filter_by_folder)) {
  3005. $add_folder_filter = " AND docs.path LIKE '" . Database::escape_string($filter_by_folder) . "%'";
  3006. }
  3007. // If we are in LP display hidden folder https://support.chamilo.org/issues/6679
  3008. $lp_visibility_condition = null;
  3009. if ($lp_id) {
  3010. // $lp_visibility_condition = " OR filetype='folder'";
  3011. if ($showInvisibleFiles) {
  3012. $lp_visibility_condition .= ' OR last.visibility = 0';
  3013. }
  3014. }
  3015. $showOnlyFoldersCondition = null;
  3016. if ($showOnlyFolders) {
  3017. //$showOnlyFoldersCondition = " AND docs.filetype = 'folder' ";
  3018. }
  3019. $folderCondition = " AND docs.path LIKE '/%' ";
  3020. if (!api_is_allowed_to_edit()) {
  3021. $protectedFolders = self::getProtectedFolderFromStudent();
  3022. foreach ($protectedFolders as $folder) {
  3023. $folderCondition .= " AND docs.path NOT LIKE '$folder' ";
  3024. }
  3025. }
  3026. if ($folderId !== false) {
  3027. $parentData = self::get_document_data_by_id($folderId, $course_info['code']);
  3028. if (!empty($parentData)) {
  3029. $cleanedPath = $parentData['path'];
  3030. $num = substr_count($cleanedPath, '/');
  3031. $notLikeCondition = null;
  3032. for ($i = 1; $i <= $num; $i++) {
  3033. $repeat = str_repeat('/%', $i+1);
  3034. $notLikeCondition .= " AND docs.path NOT LIKE '".Database::escape_string($cleanedPath.$repeat)."' ";
  3035. }
  3036. $folderCondition = " AND
  3037. docs.id <> $folderId AND
  3038. docs.path LIKE '".$cleanedPath."/%'
  3039. $notLikeCondition
  3040. ";
  3041. } else {
  3042. $folderCondition = " AND
  3043. docs.filetype = 'file' ";
  3044. }
  3045. }
  3046. $levelCondition = null;
  3047. if ($folderId === false) {
  3048. $levelCondition = " AND docs.path NOT LIKE'/%/%'";
  3049. }
  3050. $sql = "SELECT last.visibility, docs.*
  3051. FROM $tbl_item_prop AS last INNER JOIN $tbl_doc AS docs
  3052. ON (docs.id = last.ref AND docs.c_id = last.c_id)
  3053. WHERE
  3054. docs.path NOT LIKE '%_DELETED_%' AND
  3055. last.tool = '" . TOOL_DOCUMENT . "' $condition_session AND
  3056. (last.visibility = '1' $lp_visibility_condition) AND
  3057. last.visibility <> 2 AND
  3058. docs.c_id = {$course_info['real_id']} AND
  3059. last.c_id = {$course_info['real_id']}
  3060. $showOnlyFoldersCondition
  3061. $folderCondition
  3062. $levelCondition
  3063. $add_folder_filter
  3064. ORDER BY docs.filetype DESC, docs.title ASC";
  3065. $res_doc = Database::query($sql);
  3066. $resources = Database::store_result($res_doc, 'ASSOC');
  3067. $return = '';
  3068. if ($lp_id) {
  3069. if ($folderId === false) {
  3070. $return .= '<div class="lp_resource_element">';
  3071. $return .= Display::return_icon('new_doc.gif', '', array(), ICON_SIZE_SMALL);
  3072. $return .= Display::url(
  3073. get_lang('NewDocument'),
  3074. api_get_self().'?'.api_get_cidreq().'&action=add_item&type='.TOOL_DOCUMENT.'&lp_id='.$_SESSION['oLP']->lp_id
  3075. );
  3076. $return .= '</div>';
  3077. }
  3078. } else {
  3079. $return .= Display::div(
  3080. Display::url(
  3081. Display::return_icon('close.png', get_lang('Close'), array(), ICON_SIZE_SMALL),
  3082. ' javascript:void(0);',
  3083. array('id' => 'close_div_' . $course_info['real_id'] . '_' . $session_id, 'class' => 'close_div')
  3084. ),
  3085. array('style' => 'position:absolute;right:10px')
  3086. );
  3087. }
  3088. // If you want to debug it, I advise you to do "echo" on the eval statements.
  3089. $newResources = array();
  3090. if (!empty($resources) && $user_in_course) {
  3091. foreach ($resources as $resource) {
  3092. $is_visible = self::is_visible_by_id(
  3093. $resource['id'],
  3094. $course_info,
  3095. $session_id,
  3096. api_get_user_id()
  3097. );
  3098. if (!$is_visible) {
  3099. continue;
  3100. }
  3101. $newResources[] = $resource;
  3102. }
  3103. }
  3104. $label = get_lang('Documents');
  3105. if ($folderId === false) {
  3106. $documents[$label] = array(
  3107. 'id' => 0,
  3108. 'files' => $newResources
  3109. );
  3110. } else {
  3111. $documents[$parentData['title']] = array(
  3112. 'id' => intval($folderId),
  3113. 'files' => $newResources
  3114. );
  3115. }
  3116. $write_result = self::write_resources_tree(
  3117. $course_info,
  3118. $session_id,
  3119. $documents,
  3120. $lp_id,
  3121. $target,
  3122. $add_move_button,
  3123. $overwrite_url,
  3124. $folderId
  3125. );
  3126. $return .= $write_result;
  3127. $img_path = api_get_path(WEB_IMG_PATH);
  3128. if ($lp_id == false) {
  3129. $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&url='.$overwrite_url.'&lp_id='.$lp_id.'&cidReq='.$course_info['code'];
  3130. $return .= "<script>
  3131. $('.doc_folder').click(function() {
  3132. var realId = this.id;
  3133. var my_id = this.id.split('_')[2];
  3134. var tempId = 'temp_'+my_id;
  3135. $('#res_'+my_id).show();
  3136. var tempDiv = $('#'+realId).find('#'+tempId);
  3137. if (tempDiv.length == 0) {
  3138. $.ajax({
  3139. async: false,
  3140. type: 'GET',
  3141. url: '".$url."',
  3142. data: 'folder_id='+my_id,
  3143. success: function(data) {
  3144. $('#'+realId).append('<div id='+tempId+'>'+data+'</div>');
  3145. }
  3146. });
  3147. }
  3148. });
  3149. $('.close_div').click(function() {
  3150. var course_id = this.id.split('_')[2];
  3151. var session_id = this.id.split('_')[3];
  3152. $('#document_result_'+course_id+'_'+session_id).hide();
  3153. $('.lp_resource').remove();
  3154. $('.document_preview_container').html('');
  3155. });
  3156. </script>";
  3157. } else {
  3158. //For LPs
  3159. $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&lp_id='.$lp_id.'&'.api_get_cidreq();
  3160. $return .= "<script>
  3161. function testResources(id, img) {
  3162. var numericId = id.split('_')[1];
  3163. var parentId = 'doc_id_'+numericId;
  3164. var tempId = 'temp_'+numericId;
  3165. var image = $('#'+img);
  3166. if (image.hasClass('open')) {
  3167. image.removeClass('open');
  3168. image.attr('src', '" . $img_path . "nolines_plus.gif');
  3169. $('#'+id).show();
  3170. $('#'+tempId).hide();
  3171. } else {
  3172. image.addClass('open');
  3173. image.attr('src', '" . $img_path . "nolines_minus.gif');
  3174. $('#'+id).hide();
  3175. $('#'+tempId).show();
  3176. var tempDiv = $('#'+parentId).find('#'+tempId);
  3177. if (tempDiv.length == 0) {
  3178. $.ajax({
  3179. type: 'GET',
  3180. async: false,
  3181. url: '".$url."',
  3182. data: 'folder_id='+numericId,
  3183. success: function(data) {
  3184. tempDiv = $('#doc_id_'+numericId).append('<div id='+tempId+'>'+data+'</div>');
  3185. }
  3186. });
  3187. }
  3188. }
  3189. }
  3190. </script>";
  3191. }
  3192. if (!$user_in_course) {
  3193. $return = '';
  3194. }
  3195. return $return;
  3196. }
  3197. /**
  3198. * @param array $course_info
  3199. * @param int $session_id
  3200. * @param array $resource
  3201. * @param int $lp_id
  3202. * @param bool $add_move_button
  3203. * @param string $target
  3204. * @param string $overwrite_url
  3205. * @return null|string
  3206. */
  3207. private static function parseFile(
  3208. $course_info,
  3209. $session_id,
  3210. $resource,
  3211. $lp_id,
  3212. $add_move_button,
  3213. $target,
  3214. $overwrite_url
  3215. ) {
  3216. $img_path = api_get_path(WEB_IMG_PATH);
  3217. $img_sys_path = api_get_path(SYS_CODE_PATH) . 'img/';
  3218. $web_code_path = api_get_path(WEB_CODE_PATH);
  3219. $documentId = $resource['id'];
  3220. $path = $resource['path'];
  3221. if (empty($path)) {
  3222. $num = 0;
  3223. } else {
  3224. $num = substr_count($path, '/') - 1;
  3225. }
  3226. // It's a file.
  3227. $icon = choose_image($path);
  3228. $position = strrpos($icon, '.');
  3229. $icon = substr($icon, 0, $position) . '_small.gif';
  3230. $my_file_title = $resource['title'];
  3231. $visibility = $resource['visibility'];
  3232. // If title is empty we try to use the path
  3233. if (empty($my_file_title)) {
  3234. $my_file_title = basename($path);
  3235. }
  3236. // Show the "image name" not the filename of the image.
  3237. if ($lp_id) {
  3238. //LP URL
  3239. $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;
  3240. if (!empty($overwrite_url)) {
  3241. $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId.'';
  3242. }
  3243. } else {
  3244. // Direct document URL
  3245. $url = $web_code_path . 'document/document.php?cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&id=' . $documentId;
  3246. if (!empty($overwrite_url)) {
  3247. $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId;
  3248. }
  3249. }
  3250. $img = $img_path . $icon;
  3251. if (!file_exists($img_sys_path . $icon)) {
  3252. $img = $img_path . 'icons/16/default_small.gif';
  3253. }
  3254. $link = Display::url(
  3255. '<img alt="" src="' . $img . '" title="" />&nbsp;' . $my_file_title, $url,
  3256. array('target' => $target)
  3257. );
  3258. $visibilityClass = null;
  3259. if ($visibility == 0) {
  3260. $visibilityClass = ' invisible ';
  3261. }
  3262. $return = null;
  3263. if ($lp_id == false) {
  3264. $return .= '<li class="doc_resource '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
  3265. } else {
  3266. $return .= '<li class="doc_resource lp_resource_element '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
  3267. }
  3268. $return .= '<div class="item_data" style="margin-left:' . ($num * 18) . 'px;margin-right:5px;">';
  3269. if ($add_move_button) {
  3270. $return .= '<a class="moved" href="#">';
  3271. $return .= Display::return_icon('move_everywhere.png', get_lang('Move'), array(), ICON_SIZE_TINY);
  3272. $return .= '</a> ';
  3273. }
  3274. $return .= $link;
  3275. $return .= '</div></li>';
  3276. return $return;
  3277. }
  3278. /**
  3279. * @param int $folderId
  3280. * @param array $resource
  3281. * @param int $lp_id
  3282. * @return null|string
  3283. */
  3284. private static function parseFolder($folderId, $resource, $lp_id)
  3285. {
  3286. $title = isset($resource['title']) ? $resource['title'] : null;
  3287. $path = isset($resource['path']) ? $resource['path'] : null;
  3288. $img_path = api_get_path(WEB_IMG_PATH);
  3289. if (empty($path)) {
  3290. $num = 0;
  3291. } else {
  3292. $num = substr_count($path, '/');
  3293. }
  3294. // It's a folder.
  3295. //hide some folders
  3296. if (in_array($path,
  3297. array('shared_folder', 'chat_files', 'HotPotatoes_files', 'css', 'certificates'))) {
  3298. return null;
  3299. } elseif (preg_match('/_groupdocs/', $path)) {
  3300. return null;
  3301. } elseif (preg_match('/sf_user_/', $path)) {
  3302. return null;
  3303. } elseif (preg_match('/shared_folder_session_/', $path)) {
  3304. return null;
  3305. }
  3306. //trad some titles
  3307. /*
  3308. if ($key == 'images') {
  3309. $key = get_lang('Images');
  3310. } elseif ($key == 'gallery') {
  3311. $key = get_lang('Gallery');
  3312. } elseif ($key == 'flash') {
  3313. $key = get_lang('Flash');
  3314. } elseif ($key == 'audio') {
  3315. $key = get_lang('Audio');
  3316. } elseif ($key == 'video') {
  3317. $key = get_lang('Video');
  3318. }*/
  3319. $onclick = '';
  3320. // if in LP, hidden folder are displayed in grey
  3321. $folder_class_hidden = "";
  3322. if ($lp_id) {
  3323. if (isset($resource['visible']) && $resource['visible'] == 0) {
  3324. $folder_class_hidden = "doc_folder_hidden"; // in base.css
  3325. }
  3326. $onclick = 'onclick="javascript: testResources(\'res_' . $resource['id'] . '\',\'img_' . $resource['id'] . '\')"';
  3327. }
  3328. $return = null;
  3329. if (empty($path)) {
  3330. $return = '<ul class="lp_resource">';
  3331. }
  3332. $return .= '<li class="doc_folder '.$folder_class_hidden.'" id="doc_id_' . $resource['id'] . '" style="margin-left:' . ($num * 18) . 'px; ">';
  3333. $image = $img_path.'nolines_plus.gif';
  3334. if (empty($path)) {
  3335. $image = $img_path.'nolines_minus.gif';
  3336. }
  3337. $return .= '<img style="cursor: pointer;" src="'.$image.'" align="absmiddle" id="img_'.$resource['id'] . '" '.$onclick.'>';
  3338. $return .= '<img alt="" src="' . $img_path . 'lp_folder.gif" title="" align="absmiddle" />&nbsp;';
  3339. $return .= '<span '.$onclick.' style="cursor: pointer;" >'.$title.'</span>';
  3340. $return .= '</li>';
  3341. if (empty($path)) {
  3342. if ($folderId == false) {
  3343. $return .= '<div id="res_' . $resource['id'] . '" >';
  3344. } else {
  3345. $return .= '<div id="res_' . $resource['id'] . '" style="display: none;" >';
  3346. }
  3347. }
  3348. return $return;
  3349. }
  3350. /**
  3351. * Generate and return an HTML list of resources based on a given array.
  3352. * This list is used to show the course creator a list of available resources to choose from
  3353. * when creating a learning path.
  3354. * @param array $course_info
  3355. * @param int $session_id
  3356. * @param array $documents
  3357. * @param bool $lp_id
  3358. * @param string $target
  3359. * @param bool $add_move_button
  3360. * @param string $overwrite_url
  3361. * @param int $folderId
  3362. *
  3363. * @return string
  3364. */
  3365. public static function write_resources_tree(
  3366. $course_info,
  3367. $session_id,
  3368. $documents,
  3369. $lp_id = false,
  3370. $target = '',
  3371. $add_move_button = false,
  3372. $overwrite_url = null,
  3373. $folderId = false
  3374. ) {
  3375. require_once api_get_path(LIBRARY_PATH) . 'fileDisplay.lib.php';
  3376. $return = '';
  3377. if (!empty($documents)) {
  3378. foreach ($documents as $key => $resource) {
  3379. if (isset($resource['id']) && is_int($resource['id'])) {
  3380. $mainFolderResource = array(
  3381. 'id' => $resource['id'],
  3382. 'title' => $key,
  3383. );
  3384. if ($folderId === false) {
  3385. $return .= self::parseFolder($folderId, $mainFolderResource, $lp_id);
  3386. }
  3387. if (isset($resource['files'])) {
  3388. $return .= self::write_resources_tree(
  3389. $course_info,
  3390. $session_id,
  3391. $resource['files'],
  3392. $lp_id,
  3393. $target,
  3394. $add_move_button,
  3395. $overwrite_url
  3396. );
  3397. }
  3398. $return .= '</div>';
  3399. $return .= '</ul>';
  3400. } else {
  3401. if ($resource['filetype'] == 'folder') {
  3402. $return .= self::parseFolder($folderId, $resource, $lp_id);
  3403. } else {
  3404. $return .= self::parseFile(
  3405. $course_info,
  3406. $session_id,
  3407. $resource,
  3408. $lp_id,
  3409. $add_move_button,
  3410. $target,
  3411. $overwrite_url
  3412. );
  3413. }
  3414. }
  3415. }
  3416. }
  3417. return $return;
  3418. }
  3419. /**
  3420. * @param int $doc_id
  3421. * @param string $course_code
  3422. * @param int $session_id
  3423. * @param int $user_id
  3424. * @param int $groupId
  3425. * @return bool
  3426. */
  3427. public static function check_visibility_tree(
  3428. $doc_id,
  3429. $course_code,
  3430. $session_id,
  3431. $user_id,
  3432. $groupId = 0
  3433. ) {
  3434. $document_data = self::get_document_data_by_id($doc_id, $course_code, null, $session_id);
  3435. if ($session_id != 0 && !$document_data) {
  3436. $document_data = self::get_document_data_by_id($doc_id, $course_code, null, 0);
  3437. }
  3438. if (!empty($document_data)) {
  3439. // If admin or course teacher, allow anyway
  3440. if (api_is_platform_admin() || CourseManager::is_course_teacher($user_id, $course_code)) {
  3441. return true;
  3442. }
  3443. $course_info = api_get_course_info($course_code);
  3444. if ($document_data['parent_id'] == false || empty($document_data['parent_id'])) {
  3445. if (!empty($groupId)) {
  3446. return true;
  3447. }
  3448. $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
  3449. return $visible;
  3450. } else {
  3451. $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
  3452. if (!$visible) {
  3453. return false;
  3454. } else {
  3455. return self::check_visibility_tree($document_data['parent_id'], $course_code, $session_id, $user_id, $groupId);
  3456. }
  3457. }
  3458. } else {
  3459. return false;
  3460. }
  3461. }
  3462. /**
  3463. * Index a given document.
  3464. * @param int Document ID inside its corresponding course
  3465. * @param string Course code
  3466. * @param int Session ID (not used yet)
  3467. * @param string Language of document's content (defaults to course language)
  3468. * @param array Array of specific fields (['code'=>'value',...])
  3469. * @param string What to do if the file already exists (default or overwrite)
  3470. * @param bool When set to true, this runs the indexer without actually saving anything to any database
  3471. * @return bool Returns true on presumed success, false on failure
  3472. */
  3473. public static function index_document(
  3474. $docid,
  3475. $course_code,
  3476. $session_id = 0,
  3477. $lang = 'english',
  3478. $specific_fields_values = array(),
  3479. $if_exists = '',
  3480. $simulation = false
  3481. ) {
  3482. if (api_get_setting('search_enabled') !== 'true') {
  3483. return false;
  3484. }
  3485. if (empty($docid) or $docid != intval($docid)) {
  3486. return false;
  3487. }
  3488. if (empty($session_id)) {
  3489. $session_id = api_get_session_id();
  3490. }
  3491. $course_info = api_get_course_info($course_code);
  3492. $course_dir = $course_info['path'] . '/document';
  3493. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  3494. $base_work_dir = $sys_course_path . $course_dir;
  3495. $course_id = $course_info['real_id'];
  3496. $table_document = Database::get_course_table(TABLE_DOCUMENT);
  3497. $qry = "SELECT path, title FROM $table_document WHERE c_id = $course_id AND id = '$docid' LIMIT 1";
  3498. $result = Database::query($qry);
  3499. if (Database::num_rows($result) == 1) {
  3500. $row = Database::fetch_array($result);
  3501. $doc_path = api_get_path(SYS_COURSE_PATH) . $course_dir . $row['path'];
  3502. //TODO: mime_content_type is deprecated, fileinfo php extension is enabled by default as of PHP 5.3.0
  3503. // now versions of PHP on Debian testing(5.2.6-5) and Ubuntu(5.2.6-2ubuntu) are lower, so wait for a while
  3504. $doc_mime = mime_content_type($doc_path);
  3505. $allowed_mime_types = self::file_get_mime_type(true);
  3506. // 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
  3507. if (empty($doc_mime)) {
  3508. $allowed_extensions = array('doc', 'docx', 'ppt', 'pptx', 'pps', 'ppsx', 'xls', 'xlsx', 'odt', 'odp', 'ods', 'pdf', 'txt', 'rtf', 'msg', 'csv', 'html', 'htm');
  3509. $extensions = preg_split("/[\/\\.]/", $doc_path);
  3510. $doc_ext = strtolower($extensions[count($extensions) - 1]);
  3511. if (in_array($doc_ext, $allowed_extensions)) {
  3512. switch ($doc_ext) {
  3513. case 'ppt':
  3514. case 'pps':
  3515. $doc_mime = 'application/vnd.ms-powerpoint';
  3516. break;
  3517. case 'xls':
  3518. $doc_mime = 'application/vnd.ms-excel';
  3519. break;
  3520. }
  3521. }
  3522. }
  3523. //@todo move this nightmare in a search controller or something like that!!! J.M
  3524. if (in_array($doc_mime, $allowed_mime_types)) {
  3525. $file_title = $row['title'];
  3526. $file_content = self::get_text_content($doc_path, $doc_mime);
  3527. $course_code = Database::escape_string($course_code);
  3528. require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
  3529. require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php';
  3530. $ic_slide = new IndexableChunk();
  3531. $ic_slide->addValue('title', $file_title);
  3532. $ic_slide->addCourseId($course_code);
  3533. $ic_slide->addToolId(TOOL_DOCUMENT);
  3534. $xapian_data = array(
  3535. SE_COURSE_ID => $course_code,
  3536. SE_TOOL_ID => TOOL_DOCUMENT,
  3537. SE_DATA => array('doc_id' => $docid),
  3538. SE_USER => api_get_user_id(),
  3539. );
  3540. $ic_slide->xapian_data = serialize($xapian_data);
  3541. $di = new ChamiloIndexer();
  3542. $return = $di->connectDb(null, null, $lang);
  3543. require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
  3544. $specific_fields = get_specific_field_list();
  3545. // process different depending on what to do if file exists
  3546. /**
  3547. * @TODO Find a way to really verify if the file had been
  3548. * overwriten. Now all work is done at
  3549. * handle_uploaded_document() and it's difficult to verify it
  3550. */
  3551. if (!empty($if_exists) && $if_exists == 'overwrite') {
  3552. // Overwrite the file on search engine
  3553. // Actually, it consists on a delete of terms from db,
  3554. // insert new ones, create a new search engine document,
  3555. // and remove the old one
  3556. // Get search_did
  3557. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  3558. $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  3559. $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid);
  3560. $res = Database::query($sql);
  3561. if (Database::num_rows($res) > 0) {
  3562. $se_ref = Database::fetch_array($res);
  3563. if (!$simulation) {
  3564. $di->remove_document($se_ref['search_did']);
  3565. }
  3566. $all_specific_terms = '';
  3567. foreach ($specific_fields as $specific_field) {
  3568. if (!$simulation) {
  3569. delete_all_specific_field_value($course_code, $specific_field['id'], TOOL_DOCUMENT, $docid);
  3570. }
  3571. // Update search engine
  3572. if (isset($specific_fields_values[$specific_field['code']])) {
  3573. $sterms = trim($specific_fields_values[$specific_field['code']]);
  3574. } else { //if the specific field is not defined, force an empty one
  3575. $sterms = '';
  3576. }
  3577. $all_specific_terms .= ' ' . $sterms;
  3578. $sterms = explode(',', $sterms);
  3579. foreach ($sterms as $sterm) {
  3580. $sterm = trim($sterm);
  3581. if (!empty($sterm)) {
  3582. $ic_slide->addTerm($sterm, $specific_field['code']);
  3583. // updated the last param here from $value to $sterm without being sure - see commit15464
  3584. if (!$simulation) {
  3585. add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
  3586. }
  3587. }
  3588. }
  3589. }
  3590. // Add terms also to content to make terms findable by probabilistic search
  3591. $file_content = $all_specific_terms . ' ' . $file_content;
  3592. if (!$simulation) {
  3593. $ic_slide->addValue('content', $file_content);
  3594. $di->addChunk($ic_slide);
  3595. // Index and return a new search engine document id
  3596. $did = $di->index();
  3597. if ($did) {
  3598. // update the search_did on db
  3599. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  3600. $sql = 'UPDATE %s SET search_did=%d WHERE id=%d LIMIT 1';
  3601. $sql = sprintf($sql, $tbl_se_ref, (int) $did, (int) $se_ref['id']);
  3602. Database::query($sql);
  3603. }
  3604. }
  3605. }
  3606. } else {
  3607. // Add all terms
  3608. $all_specific_terms = '';
  3609. foreach ($specific_fields as $specific_field) {
  3610. if (isset($specific_fields_values[$specific_field['code']])) {
  3611. $sterms = trim($specific_fields_values[$specific_field['code']]);
  3612. } else { //if the specific field is not defined, force an empty one
  3613. $sterms = '';
  3614. }
  3615. $all_specific_terms .= ' ' . $sterms;
  3616. if (!empty($sterms)) {
  3617. $sterms = explode(',', $sterms);
  3618. foreach ($sterms as $sterm) {
  3619. if (!$simulation) {
  3620. $ic_slide->addTerm(trim($sterm), $specific_field['code']);
  3621. add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
  3622. }
  3623. }
  3624. }
  3625. }
  3626. // Add terms also to content to make terms findable by probabilistic search
  3627. $file_content = $all_specific_terms . ' ' . $file_content;
  3628. if (!$simulation) {
  3629. $ic_slide->addValue('content', $file_content);
  3630. $di->addChunk($ic_slide);
  3631. // Index and return search engine document id
  3632. $did = $di->index();
  3633. if ($did) {
  3634. // Save it to db
  3635. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  3636. $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
  3637. VALUES (NULL , \'%s\', \'%s\', %s, %s)';
  3638. $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid, $did);
  3639. Database::query($sql);
  3640. } else {
  3641. return false;
  3642. }
  3643. }
  3644. }
  3645. } else {
  3646. return false;
  3647. }
  3648. }
  3649. return true;
  3650. }
  3651. /**
  3652. * @return array
  3653. */
  3654. public static function get_web_odf_extension_list()
  3655. {
  3656. return array('ods', 'odt', 'odp');
  3657. }
  3658. /**
  3659. * Set of extension allowed to use Jodconverter
  3660. * @param $mode 'from'
  3661. * 'to'
  3662. * 'all'
  3663. * @param $format 'text'
  3664. * 'spreadsheet'
  3665. * 'presentation'
  3666. * 'drawing'
  3667. * 'all'
  3668. * @return array
  3669. */
  3670. public static function getJodconverterExtensionList($mode, $format)
  3671. {
  3672. $extensionList = array();
  3673. $extensionListFromText = array(
  3674. 'odt',
  3675. 'sxw',
  3676. 'rtf',
  3677. 'doc',
  3678. 'docx',
  3679. 'wpd',
  3680. 'txt',
  3681. );
  3682. $extensionListToText = array(
  3683. 'pdf',
  3684. 'odt',
  3685. 'sxw',
  3686. 'rtf',
  3687. 'doc',
  3688. 'docx',
  3689. 'txt',
  3690. );
  3691. $extensionListFromSpreadsheet = array(
  3692. 'ods',
  3693. 'sxc',
  3694. 'xls',
  3695. 'xlsx',
  3696. 'csv',
  3697. 'tsv',
  3698. );
  3699. $extensionListToSpreadsheet = array(
  3700. 'pdf',
  3701. 'ods',
  3702. 'sxc',
  3703. 'xls',
  3704. 'xlsx',
  3705. 'csv',
  3706. 'tsv',
  3707. );
  3708. $extensionListFromPresentation = array(
  3709. 'odp',
  3710. 'sxi',
  3711. 'ppt',
  3712. 'pptx',
  3713. );
  3714. $extensionListToPresentation = array(
  3715. 'pdf',
  3716. 'swf',
  3717. 'odp',
  3718. 'sxi',
  3719. 'ppt',
  3720. 'pptx',
  3721. );
  3722. $extensionListFromDrawing = array('odg');
  3723. $extensionListToDrawing = array('svg', 'swf');
  3724. if ($mode === 'from') {
  3725. if ($format === 'text') {
  3726. $extensionList = array_merge($extensionList, $extensionListFromText);
  3727. } elseif ($format === 'spreadsheet') {
  3728. $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
  3729. } elseif ($format === 'presentation') {
  3730. $extensionList = array_merge($extensionList, $extensionListFromPresentation);
  3731. } elseif ($format === 'drawing') {
  3732. $extensionList = array_merge($extensionList, $extensionListFromDrawing);
  3733. } elseif ($format === 'all') {
  3734. $extensionList = array_merge($extensionList, $extensionListFromText);
  3735. $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
  3736. $extensionList = array_merge($extensionList, $extensionListFromPresentation);
  3737. $extensionList = array_merge($extensionList, $extensionListFromDrawing);
  3738. }
  3739. } elseif ($mode === 'to') {
  3740. if ($format === 'text') {
  3741. $extensionList = array_merge($extensionList, $extensionListToText);
  3742. } elseif ($format === 'spreadsheet') {
  3743. $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
  3744. } elseif ($format === 'presentation') {
  3745. $extensionList = array_merge($extensionList, $extensionListToPresentation);
  3746. } elseif ($format === 'drawing') {
  3747. $extensionList = array_merge($extensionList, $extensionListToDrawing);
  3748. } elseif ($format === 'all') {
  3749. $extensionList = array_merge($extensionList, $extensionListToText);
  3750. $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
  3751. $extensionList = array_merge($extensionList, $extensionListToPresentation);
  3752. $extensionList = array_merge($extensionList, $extensionListToDrawing);
  3753. }
  3754. } elseif ($mode === 'all') {
  3755. if ($format === 'text') {
  3756. $extensionList = array_merge($extensionList, $extensionListFromText);
  3757. $extensionList = array_merge($extensionList, $extensionListToText);
  3758. } elseif ($format === 'spreadsheet') {
  3759. $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
  3760. $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
  3761. } elseif ($format === 'presentation') {
  3762. $extensionList = array_merge($extensionList, $extensionListFromPresentation);
  3763. $extensionList = array_merge($extensionList, $extensionListToPresentation);
  3764. } elseif ($format === 'drawing') {
  3765. $extensionList = array_merge($extensionList, $extensionListFromDrawing);
  3766. $extensionList = array_merge($extensionList, $extensionListToDrawing);
  3767. } elseif ($format === 'all') {
  3768. $extensionList = array_merge($extensionList, $extensionListFromText);
  3769. $extensionList = array_merge($extensionList, $extensionListToText);
  3770. $extensionList = array_merge($extensionList, $extensionListFromSpreadsheet);
  3771. $extensionList = array_merge($extensionList, $extensionListToSpreadsheet);
  3772. $extensionList = array_merge($extensionList, $extensionListFromPresentation);
  3773. $extensionList = array_merge($extensionList, $extensionListToPresentation);
  3774. $extensionList = array_merge($extensionList, $extensionListFromDrawing);
  3775. $extensionList = array_merge($extensionList, $extensionListToDrawing);
  3776. }
  3777. }
  3778. return $extensionList;
  3779. }
  3780. /**
  3781. * Get Format type list by extension and mode
  3782. * @param string $mode Mode to search format type list
  3783. * @example 'from'
  3784. * @example 'to'
  3785. * @param string $extension file extension to check file type
  3786. * @return array
  3787. */
  3788. public static function getFormatTypeListConvertor($mode = 'from', $extension)
  3789. {
  3790. $formatTypesList = array();
  3791. $formatTypes = array('text', 'spreadsheet', 'presentation', 'drawing');
  3792. foreach ($formatTypes as $formatType) {
  3793. if (
  3794. in_array(
  3795. $extension,
  3796. self::getJodconverterExtensionList($mode, $formatType)
  3797. )
  3798. ) {
  3799. $formatTypesList[] = $formatType;
  3800. }
  3801. }
  3802. return $formatTypesList;
  3803. }
  3804. /**
  3805. * @param string $path
  3806. * @param bool $is_certificate_mode
  3807. * @return bool
  3808. */
  3809. public static function is_folder_to_avoid($path, $is_certificate_mode = false)
  3810. {
  3811. $foldersToAvoid = array(
  3812. '/HotPotatoes_files',
  3813. '/certificates',
  3814. );
  3815. $systemFolder = api_get_course_setting('show_system_folders');
  3816. if ($systemFolder == 1) {
  3817. $foldersToAvoid = array();
  3818. }
  3819. if (basename($path) == 'css') {
  3820. return true;
  3821. }
  3822. if ($is_certificate_mode == false) {
  3823. //Certificate results
  3824. if (strstr($path, 'certificates')) {
  3825. return true;
  3826. }
  3827. }
  3828. // Admin setting for Hide/Show the folders of all users
  3829. if (api_get_setting('show_users_folders') == 'false') {
  3830. $foldersToAvoid[] = '/shared_folder';
  3831. if (strstr($path, 'shared_folder_session_')) {
  3832. return true;
  3833. }
  3834. }
  3835. // Admin setting for Hide/Show Default folders to all users
  3836. if (api_get_setting('show_default_folders') == 'false') {
  3837. $foldersToAvoid[] = '/images';
  3838. $foldersToAvoid[] = '/flash';
  3839. $foldersToAvoid[] = '/audio';
  3840. $foldersToAvoid[] = '/video';
  3841. }
  3842. // Admin setting for Hide/Show chat history folder
  3843. if (api_get_setting('show_chat_folder') == 'false') {
  3844. $foldersToAvoid[] = '/chat_files';
  3845. }
  3846. if (is_array($foldersToAvoid)) {
  3847. return in_array($path, $foldersToAvoid);
  3848. } else {
  3849. return false;
  3850. }
  3851. }
  3852. /**
  3853. * @return array
  3854. */
  3855. public static function get_system_folders()
  3856. {
  3857. return array(
  3858. '/certificates',
  3859. '/HotPotatoes_files',
  3860. '/chat_files',
  3861. '/images',
  3862. '/flash',
  3863. '/audio',
  3864. '/video',
  3865. '/shared_folder',
  3866. '/learning_path'
  3867. );
  3868. }
  3869. /**
  3870. * @return array
  3871. */
  3872. public static function getProtectedFolderFromStudent()
  3873. {
  3874. return array(
  3875. '/certificates',
  3876. '/HotPotatoes_files',
  3877. '/chat_files',
  3878. '/shared_folder',
  3879. '/learning_path'
  3880. );
  3881. }
  3882. /**
  3883. * @param string $courseCode
  3884. * @return string 'visible' or 'invisible' string
  3885. */
  3886. public static function getDocumentDefaultVisibility($courseCode)
  3887. {
  3888. $settings = api_get_setting('tool_visible_by_default_at_creation');
  3889. $defaultVisibility = 'visible';
  3890. if (isset($settings['documents'])) {
  3891. $portalDefaultVisibility = 'invisible';
  3892. if ($settings['documents'] == 'true') {
  3893. $portalDefaultVisibility = 'visible';
  3894. }
  3895. $defaultVisibility = $portalDefaultVisibility;
  3896. }
  3897. if (api_get_setting('documents_default_visibility_defined_in_course') == 'true') {
  3898. $courseVisibility = api_get_course_setting('documents_default_visibility', $courseCode);
  3899. if (!empty($courseVisibility) && in_array($courseVisibility, array('visible', 'invisible'))) {
  3900. $defaultVisibility = $courseVisibility;
  3901. }
  3902. }
  3903. return $defaultVisibility;
  3904. }
  3905. /**
  3906. * @param array $courseInfo
  3907. * @param int $id doc id
  3908. * @param string $visibility visible/invisible
  3909. * @param int $userId
  3910. */
  3911. public static function updateVisibilityFromAllSessions($courseInfo, $id, $visibility, $userId)
  3912. {
  3913. $sessionList = SessionManager::get_session_by_course($courseInfo['code']);
  3914. if (!empty($sessionList)) {
  3915. foreach ($sessionList as $session) {
  3916. $sessionId = $session['id'];
  3917. api_item_property_update(
  3918. $courseInfo,
  3919. TOOL_DOCUMENT,
  3920. $id,
  3921. $visibility,
  3922. $userId,
  3923. null,
  3924. null,
  3925. null,
  3926. null,
  3927. $sessionId
  3928. );
  3929. }
  3930. }
  3931. }
  3932. /**
  3933. * @param string $file
  3934. * @return string
  3935. */
  3936. public static function readNanogongFile($file)
  3937. {
  3938. $nanoGongJarFile = api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar';
  3939. $html = '<applet id="applet" archive="'.$nanoGongJarFile.'" code="gong.NanoGong" width="160" height="95">';
  3940. $html .= '<param name="SoundFileURL" value="'.$file.'" />';
  3941. $html .= '<param name="ShowSaveButton" value="false" />';
  3942. $html .= '<param name="ShowTime" value="true" />';
  3943. $html .= '<param name="ShowRecordButton" value="false" />';
  3944. $html .= '</applet>';
  3945. return $html;
  3946. }
  3947. /**
  3948. * @param string $filePath
  3949. * @param string $path
  3950. * @param array $courseInfo
  3951. * @param int $sessionId
  3952. * @param string $whatIfFileExists overwrite|rename
  3953. * @param int $userId
  3954. * @param int $groupId
  3955. * @param int $toUserId
  3956. * @param string $comment
  3957. * @return bool|path
  3958. */
  3959. public static function addFileToDocumentTool(
  3960. $filePath,
  3961. $path,
  3962. $courseInfo,
  3963. $sessionId,
  3964. $userId,
  3965. $whatIfFileExists = 'overwrite',
  3966. $groupId = null,
  3967. $toUserId = null,
  3968. $comment = null
  3969. ) {
  3970. if (!file_exists($filePath)) {
  3971. return false;
  3972. }
  3973. $fileInfo = pathinfo($filePath);
  3974. $file = array(
  3975. 'name' => $fileInfo['basename'],
  3976. 'tmp_name' => $filePath,
  3977. 'size' => filesize($filePath),
  3978. 'from_file' => true
  3979. );
  3980. $course_dir = $courseInfo['path'].'/document';
  3981. $baseWorkDir = api_get_path(SYS_COURSE_PATH).$course_dir;
  3982. $filePath = handle_uploaded_document(
  3983. $courseInfo,
  3984. $file,
  3985. $baseWorkDir,
  3986. $path,
  3987. $userId,
  3988. $groupId,
  3989. $toUserId,
  3990. false,
  3991. $whatIfFileExists,
  3992. false,
  3993. false,
  3994. $comment,
  3995. $sessionId
  3996. );
  3997. if ($filePath) {
  3998. return DocumentManager::get_document_id(
  3999. $courseInfo,
  4000. $filePath,
  4001. $sessionId
  4002. );
  4003. }
  4004. return false;
  4005. }
  4006. /**
  4007. * Converts wav to mp3 file.
  4008. * Requires the ffmpeg lib. In ubuntu: sudo apt-get install ffmpeg
  4009. * @param string $wavFile
  4010. * @param bool $removeWavFileIfSuccess
  4011. * @return bool
  4012. */
  4013. public static function convertWavToMp3($wavFile, $removeWavFileIfSuccess = false)
  4014. {
  4015. require_once '../../../../vendor/autoload.php';
  4016. if (file_exists($wavFile)) {
  4017. try {
  4018. $ffmpeg = \FFMpeg\FFMpeg::create();
  4019. $video = $ffmpeg->open($wavFile);
  4020. $mp3File = str_replace('wav', 'mp3', $wavFile);
  4021. $result = $video->save(new FFMpeg\Format\Audio\Mp3(), $mp3File);
  4022. if ($result && $removeWavFileIfSuccess) {
  4023. unlink($wavFile);
  4024. }
  4025. if (file_exists($mp3File)) {
  4026. return $mp3File;
  4027. }
  4028. } catch (Exception $e) {
  4029. error_log($e->getMessage());
  4030. error_log($e->getPrevious()->getMessage());
  4031. }
  4032. }
  4033. return false;
  4034. }
  4035. /**
  4036. * @param string $documentData wav document information
  4037. * @param array $courseInfo
  4038. * @param int $sessionId
  4039. * @param int $userId user that adds the document
  4040. * @param string $whatIfFileExists
  4041. * @param bool $deleteWavFile
  4042. *
  4043. * @return bool
  4044. */
  4045. public static function addAndConvertWavToMp3(
  4046. $documentData,
  4047. $courseInfo,
  4048. $sessionId,
  4049. $userId,
  4050. $whatIfFileExists = 'overwrite',
  4051. $deleteWavFile = false
  4052. ) {
  4053. if (empty($documentData)) {
  4054. return false;
  4055. }
  4056. if (isset($documentData['absolute_path']) &&
  4057. file_exists($documentData['absolute_path'])
  4058. ) {
  4059. $mp3FilePath = self::convertWavToMp3($documentData['absolute_path']);
  4060. if (!empty($mp3FilePath) && file_exists($mp3FilePath)) {
  4061. $documentId = self::addFileToDocumentTool(
  4062. $mp3FilePath,
  4063. dirname($documentData['path']),
  4064. $courseInfo,
  4065. $sessionId,
  4066. $userId,
  4067. $whatIfFileExists,
  4068. null,
  4069. null,
  4070. $documentData['comment']
  4071. );
  4072. if (!empty($documentId)) {
  4073. if ($deleteWavFile) {
  4074. $coursePath = $courseInfo['directory'].'/document';
  4075. $documentPath = api_get_path(SYS_COURSE_PATH).$coursePath;
  4076. self::delete_document(
  4077. $courseInfo,
  4078. null,
  4079. $documentPath,
  4080. $sessionId,
  4081. $documentData['id']
  4082. );
  4083. }
  4084. return $documentId;
  4085. }
  4086. }
  4087. }
  4088. return false;
  4089. }
  4090. /**
  4091. * Sets
  4092. * @param string $file ($document_data['path'])
  4093. * @param string $file_url_sys
  4094. * @return string
  4095. */
  4096. public static function generateAudioTempFile($file, $file_url_sys)
  4097. {
  4098. //make temp audio
  4099. $temp_folder = api_get_path(SYS_ARCHIVE_PATH).'temp/audio';
  4100. if (!file_exists($temp_folder)) {
  4101. @mkdir($temp_folder, api_get_permissions_for_new_directories(), true);
  4102. }
  4103. //make htaccess with allow from all, and file index.html into temp/audio
  4104. $htaccess = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess';
  4105. if (!file_exists($htaccess)) {
  4106. $htaccess_content="order deny,allow\r\nallow from all\r\nOptions -Indexes";
  4107. $fp = @ fopen(api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess', 'w');
  4108. if ($fp) {
  4109. fwrite($fp, $htaccess_content);
  4110. fclose($fp);
  4111. }
  4112. }
  4113. //encript temp name file
  4114. $name_crip = sha1(uniqid());//encript
  4115. $findext= explode(".", $file);
  4116. $extension = $findext[count($findext)-1];
  4117. $file_crip = $name_crip.'.'.$extension;
  4118. //copy file to temp/audio directory
  4119. $from_sys = $file_url_sys;
  4120. $to_sys = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/'.$file_crip;
  4121. if (file_exists($from_sys)) {
  4122. copy($from_sys, $to_sys);
  4123. }
  4124. //get file from tmp directory
  4125. $_SESSION['temp_audio_nanogong'] = $to_sys;
  4126. return api_get_path(WEB_ARCHIVE_PATH).'temp/audio/'.$file_crip;
  4127. }
  4128. /**
  4129. * Erase temp nanogong audio.
  4130. */
  4131. public static function removeGeneratedAudioTempFile()
  4132. {
  4133. if (isset($_SESSION['temp_audio_nanogong'])
  4134. && !empty($_SESSION['temp_audio_nanogong'])
  4135. && is_file($_SESSION['temp_audio_nanogong'])) {
  4136. unlink($_SESSION['temp_audio_nanogong']);
  4137. unset($_SESSION['temp_audio_nanogong']);
  4138. }
  4139. }
  4140. /**
  4141. * Check if the past is used in this course.
  4142. * @param array $courseInfo
  4143. * @param string $path
  4144. *
  4145. * @return array
  4146. */
  4147. public static function getDocumentByPathInCourse($courseInfo, $path)
  4148. {
  4149. $table = Database::get_course_table(TABLE_DOCUMENT);
  4150. $path = Database::escape_string($path);
  4151. $courseId = $courseInfo['real_id'];
  4152. if (empty($courseId)) {
  4153. return false;
  4154. }
  4155. $sql = "SELECT * FROM $table WHERE c_id = $courseId AND path = '$path'";
  4156. $result = Database::query($sql);
  4157. return Database::store_result($result, 'ASSOC');
  4158. }
  4159. /**
  4160. * @param array $_course
  4161. * @return int
  4162. */
  4163. public static function createDefaultAudioFolder($_course)
  4164. {
  4165. if (!isset($_course['path'])) {
  4166. return false;
  4167. }
  4168. $audioId = null;
  4169. $path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document/';
  4170. if (!is_dir($path.'audio')) {
  4171. mkdir($path.'audio', api_get_permissions_for_new_directories());
  4172. $audioId = add_document($_course, '/audio', 'folder', 0, 'Audio');
  4173. api_item_property_update(
  4174. $_course,
  4175. TOOL_DOCUMENT,
  4176. $audioId,
  4177. 'FolderCreated',
  4178. api_get_user_id(),
  4179. null,
  4180. null,
  4181. null,
  4182. null,
  4183. api_get_session_id()
  4184. );
  4185. }
  4186. return $audioId;
  4187. }
  4188. /**
  4189. * Generate a default certificate for a courses
  4190. *
  4191. * @global string $css CSS directory
  4192. * @global string $img_dir image directory
  4193. * @global string $default_course_dir Course directory
  4194. * @global string $js JS directory
  4195. * @param array $courseData The course info
  4196. */
  4197. public static function generateDefaultCertificate($courseData)
  4198. {
  4199. global $css, $img_dir, $default_course_dir, $js;
  4200. $codePath = api_get_path(REL_CODE_PATH);
  4201. $dir = '/certificates';
  4202. // Create certificates directory if it doesn't exist
  4203. DocumentManager::create_directory_certificate_in_course($courseData['code']);
  4204. $title = get_lang('DefaultCertificate');
  4205. $comment = null;
  4206. $fileName = replace_dangerous_char($title);
  4207. $filePath = api_get_path(SYS_COURSE_PATH) . "{$courseData['path']}/document{$dir}";
  4208. $fileFullPath = "{$filePath}/{$fileName}.html";
  4209. $fileSize = 0;
  4210. $fileType = 'file';
  4211. $templateContent = file_get_contents(api_get_path(SYS_CODE_PATH) . 'gradebook/certificate_template/template.html');
  4212. $search = array('{CSS}', '{IMG_DIR}', '{REL_CODE_PATH}', '{COURSE_DIR}');
  4213. $replace = array($css.$js, $img_dir, $codePath, $default_course_dir);
  4214. $fileContent = str_replace($search, $replace, $templateContent);
  4215. $saveFilePath = "{$dir}/{$fileName}.html";
  4216. if (!is_dir($filePath)) {
  4217. mkdir($filePath, api_get_permissions_for_new_directories());
  4218. }
  4219. $defaultCertificateFile = $fp = @fopen($fileFullPath, 'w');
  4220. if ($defaultCertificateFile != false) {
  4221. @fputs($defaultCertificateFile, $fileContent);
  4222. fclose($defaultCertificateFile);
  4223. chmod($fileFullPath, api_get_permissions_for_new_files());
  4224. $fileSize = filesize($fileFullPath);
  4225. }
  4226. $documentId = add_document($courseData, $saveFilePath, $fileType, $fileSize, $title, $comment);
  4227. $defaultCertificateId = self::get_default_certificate_id($courseData['code']);
  4228. if (!isset($defaultCertificateId)) {
  4229. self::attach_gradebook_certificate($courseData['code'], $documentId);
  4230. }
  4231. }
  4232. /**
  4233. * Get folder/file suffix
  4234. *
  4235. * @param array $courseInfo
  4236. * @param int $sessionId
  4237. * @param int $groupId
  4238. *
  4239. * @return string
  4240. */
  4241. public static function getDocumentSuffix($courseInfo, $sessionId, $groupId)
  4242. {
  4243. // If no session or group, then no suffix.
  4244. if (empty($sessionId) && empty($groupId)) {
  4245. return '';
  4246. }
  4247. return '__'.intval($sessionId).'__'.intval($groupId);
  4248. }
  4249. /**
  4250. * Fix a document name adding session id and group id
  4251. * Turns picture.jpg -> picture__1__2.jpg
  4252. * Where 1 = session id and 2 group id
  4253. * Of session id and group id are empty then the function returns:
  4254. * picture.jpg -> picture.jpg
  4255. *
  4256. * @param string $name folder or file name
  4257. * @param string $type 'folder' or 'file'
  4258. * @param array $courseInfo
  4259. * @param int $sessionId
  4260. * @param int $groupId
  4261. *
  4262. * @return string
  4263. */
  4264. public static function fixDocumentName($name, $type, $courseInfo, $sessionId, $groupId)
  4265. {
  4266. $suffix = self::getDocumentSuffix($courseInfo, $sessionId, $groupId);
  4267. switch ($type) {
  4268. case 'folder':
  4269. $name = $name.$suffix;
  4270. break;
  4271. case 'file':
  4272. $name = self::addSuffixToFileName($name, $suffix);
  4273. break;
  4274. }
  4275. return $name;
  4276. }
  4277. /**
  4278. * Add a suffix to a file Example:
  4279. * /folder/picture.jpg => to /folder/picture_this.jpg
  4280. * where "_this" is the suffix
  4281. * @param string $name
  4282. * @param string $suffix
  4283. * @return string
  4284. */
  4285. public static function addSuffixToFileName($name, $suffix)
  4286. {
  4287. $extension = pathinfo($name, PATHINFO_EXTENSION);
  4288. $fileName = pathinfo($name, PATHINFO_FILENAME);
  4289. $dir = pathinfo($name, PATHINFO_DIRNAME);
  4290. if ($dir == '.') {
  4291. $dir = null;
  4292. }
  4293. if (!empty($dir) && $dir != '/') {
  4294. $dir = $dir.'/';
  4295. }
  4296. $name = $dir.$fileName.$suffix.'.'.$extension;
  4297. return $name;
  4298. }
  4299. /**
  4300. * Check if folder exist in the course base or in the session course
  4301. * @param string $folder Example: /folder/folder2
  4302. * @param array $courseInfo
  4303. * @param int $sessionId
  4304. * @param int $groupId
  4305. *
  4306. * @return bool
  4307. */
  4308. public static function folderExists(
  4309. $folder,
  4310. $courseInfo,
  4311. $sessionId,
  4312. $groupId,
  4313. $useSuffix = true
  4314. ) {
  4315. $courseId = $courseInfo['real_id'];
  4316. if (empty($courseId)) {
  4317. return false;
  4318. }
  4319. $sessionId = intval($sessionId);
  4320. $folderWithSuffix = $folder;
  4321. if ($useSuffix) {
  4322. $folderWithSuffix = self::fixDocumentName(
  4323. $folder,
  4324. 'folder',
  4325. $courseInfo,
  4326. $sessionId,
  4327. $groupId
  4328. );
  4329. }
  4330. $folder = Database::escape_string($folder);
  4331. $folderWithSuffix = Database::escape_string($folderWithSuffix);
  4332. // Check if pathname already exists inside document table
  4333. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  4334. $sql = "SELECT id, path FROM $tbl_document
  4335. WHERE
  4336. filetype = 'folder' AND
  4337. c_id = $courseId AND
  4338. (path = '$folder' OR path = '$folderWithSuffix') AND
  4339. (session_id = 0 OR session_id = $sessionId)
  4340. ";
  4341. $rs = Database::query($sql);
  4342. if (Database::num_rows($rs)) {
  4343. return true;
  4344. }
  4345. return false;
  4346. }
  4347. /**
  4348. * Check if file exist in the course base or in the session course
  4349. * @param string $fileName Example: /folder/picture.jpg
  4350. * @param array $courseInfo
  4351. * @param int $sessionId
  4352. * @param int $groupId
  4353. *
  4354. * @return bool
  4355. */
  4356. public static function documentExists(
  4357. $fileName,
  4358. $courseInfo,
  4359. $sessionId,
  4360. $groupId
  4361. ) {
  4362. $courseId = $courseInfo['real_id'];
  4363. if (empty($courseId)) {
  4364. return false;
  4365. }
  4366. $sessionId = intval($sessionId);
  4367. $fileNameEscape = Database::escape_string($fileName);
  4368. $fileNameWithSuffix = self::fixDocumentName(
  4369. $fileName,
  4370. 'file',
  4371. $courseInfo,
  4372. $sessionId,
  4373. $groupId
  4374. );
  4375. $fileNameWithSuffix = Database::escape_string($fileNameWithSuffix);
  4376. // Check if pathname already exists inside document table
  4377. $table = Database::get_course_table(TABLE_DOCUMENT);
  4378. $sql = "SELECT id, path FROM $table
  4379. WHERE
  4380. filetype = 'file' AND
  4381. c_id = $courseId AND
  4382. (
  4383. path = '".$fileNameEscape."' OR
  4384. path = '$fileNameWithSuffix'
  4385. ) AND
  4386. (session_id = 0 OR session_id = $sessionId)
  4387. ";
  4388. $rs = Database::query($sql);
  4389. if (Database::num_rows($rs)) {
  4390. return true;
  4391. }
  4392. return false;
  4393. }
  4394. /**
  4395. * Undo the suffix applied to a file example:
  4396. * turns picture__1__1.jpg to picture.jpg
  4397. * @param string $name
  4398. * @param int $courseId
  4399. * @param int $sessionId
  4400. * @param int $groupId
  4401. *
  4402. * @return string
  4403. */
  4404. public static function undoFixDocumentName(
  4405. $name,
  4406. $courseId,
  4407. $sessionId,
  4408. $groupId
  4409. ) {
  4410. if (empty($sessionId) && empty($groupId)) {
  4411. return $name;
  4412. }
  4413. $suffix = self::getDocumentSuffix(
  4414. array('real_id' => $courseId),
  4415. $sessionId,
  4416. $groupId
  4417. );
  4418. $name = str_replace($suffix, '', $name);
  4419. return $name;
  4420. }
  4421. /**
  4422. * @param string $path
  4423. * @param string $name
  4424. * @param array $courseInfo
  4425. * @param int $sessionId
  4426. * @param int $groupId
  4427. *
  4428. * @return string
  4429. */
  4430. public static function getUniqueFileName($path, $name, $courseInfo, $sessionId, $groupId)
  4431. {
  4432. $counter = 1;
  4433. $filePath = $path.$name;
  4434. $uniqueName = $name;
  4435. while ($documentExists = self::documentExists(
  4436. $filePath,
  4437. $courseInfo,
  4438. $sessionId,
  4439. $groupId
  4440. )) {
  4441. $uniqueName = self::addSuffixToFileName($name, '_' . $counter);
  4442. $filePath = $path . $uniqueName;
  4443. $counter++;
  4444. }
  4445. return $uniqueName;
  4446. }
  4447. /**
  4448. * @param array $courseInfo
  4449. * @param int $sessionId
  4450. *
  4451. * @return array
  4452. */
  4453. public static function getDeletedDocuments($courseInfo, $sessionId = 0)
  4454. {
  4455. $table = Database::get_course_table(TABLE_DOCUMENT);
  4456. $courseId = $courseInfo['real_id'];
  4457. $sessionCondition = api_get_session_condition($sessionId);
  4458. $sql = "SELECT * FROM $table
  4459. WHERE
  4460. path LIKE '%DELETED%' AND
  4461. c_id = $courseId
  4462. $sessionCondition
  4463. ORDER BY path
  4464. ";
  4465. $result = Database::query($sql);
  4466. $files = array();
  4467. while ($document = Database::fetch_array($result, 'ASSOC')) {
  4468. $files[] = $document;
  4469. }
  4470. return $files;
  4471. }
  4472. /**
  4473. * @param int $id
  4474. * @param array $courseInfo
  4475. * @param int $sessionId
  4476. *
  4477. * @return array
  4478. */
  4479. public static function getDeletedDocument($id, $courseInfo, $sessionId = 0)
  4480. {
  4481. if (empty($courseInfo)) {
  4482. return false;
  4483. }
  4484. $table = Database::get_course_table(TABLE_DOCUMENT);
  4485. $courseId = $courseInfo['real_id'];
  4486. $sessionCondition = api_get_session_condition($sessionId);
  4487. $sql = "SELECT * FROM $table
  4488. WHERE
  4489. path LIKE '%DELETED%' AND
  4490. id = $id AND
  4491. c_id = $courseId
  4492. $sessionCondition
  4493. LIMIT 1
  4494. ";
  4495. $result = Database::query($sql);
  4496. if (Database::num_rows($result)) {
  4497. $result = Database::fetch_array($result, 'ASSOC');
  4498. return $result;
  4499. }
  4500. return array();
  4501. }
  4502. /**
  4503. * @param int $id
  4504. * @param array $courseInfo
  4505. * @param int $sessionId
  4506. * @return bool
  4507. */
  4508. public static function purgeDocument($id, $courseInfo, $sessionId = 0)
  4509. {
  4510. $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
  4511. if (!empty($document)) {
  4512. $path = $document['path'];
  4513. $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
  4514. my_delete($coursePath.$path);
  4515. // Hard delete.
  4516. self::deleteDocumentFromDb($id, $courseInfo, $sessionId, true);
  4517. return true;
  4518. }
  4519. return false;
  4520. }
  4521. /**
  4522. * @param array $courseInfo
  4523. * @param int $sessionId
  4524. */
  4525. public static function purgeDocuments($courseInfo, $sessionId)
  4526. {
  4527. $files = self::getDeletedDocuments($courseInfo, $sessionId);
  4528. foreach ($files as $file) {
  4529. self::purgeDocument($file['id'], $courseInfo, $sessionId);
  4530. }
  4531. }
  4532. /**
  4533. * @param int $id
  4534. * @param array $courseInfo
  4535. * @param int $sessionId
  4536. * @return bool
  4537. */
  4538. public static function downloadDeletedDocument($id, $courseInfo, $sessionId)
  4539. {
  4540. $document = self::getDeletedDocument($id, $courseInfo, $sessionId);
  4541. if (!empty($document)) {
  4542. $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document/';
  4543. if (Security::check_abs_path($coursePath.$document['path'], $coursePath)) {
  4544. self::file_send_for_download($coursePath.$document['path']);
  4545. exit;
  4546. }
  4547. }
  4548. }
  4549. /**
  4550. * @param array $courseInfo
  4551. * @param int $sessionId
  4552. *
  4553. * @return bool
  4554. */
  4555. public static function downloadAllDeletedDocument($courseInfo, $sessionId)
  4556. {
  4557. // Zip library for creation of the zip file.
  4558. require api_get_path(LIBRARY_PATH).'pclzip/pclzip.lib.php';
  4559. $files = self::getDeletedDocuments($courseInfo, $sessionId);
  4560. if (empty($files)) {
  4561. return false;
  4562. }
  4563. $coursePath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
  4564. // Creating a ZIP file.
  4565. $tempZipFile = api_get_path(SYS_ARCHIVE_PATH).api_get_unique_id().".zip";
  4566. $zip = new PclZip($tempZipFile);
  4567. foreach ($files as $file) {
  4568. $zip->add(
  4569. $coursePath.$file['path'],
  4570. PCLZIP_OPT_REMOVE_PATH,
  4571. $coursePath
  4572. );
  4573. }
  4574. if (Security::check_abs_path($tempZipFile, api_get_path(SYS_ARCHIVE_PATH))) {
  4575. DocumentManager::file_send_for_download($tempZipFile, true);
  4576. @unlink($tempZipFile);
  4577. exit;
  4578. }
  4579. }
  4580. }