document.lib.php 191 KB

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