html.formfile.class.php 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178
  1. <?php
  2. /* Copyright (C) 2008-2013 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2010-2014 Regis Houssin <regis.houssin@inodbox.com>
  4. * Copyright (C) 2010-2016 Juanjo Menent <jmenent@2byte.es>
  5. * Copyright (C) 2013 Charles-Fr BENKE <charles.fr@benke.fr>
  6. * Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
  7. * Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
  8. * Copyright (C) 2015 Bahfir Abbes <bafbes@gmail.com>
  9. * Copyright (C) 2016-2017 Ferran Marcet <fmarcet@2byte.es>
  10. * Copyright (C) 2019-2022 Frédéric France <frederic.france@netlogic.fr>
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 3 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  24. */
  25. /**
  26. * \file htdocs/core/class/html.formfile.class.php
  27. * \ingroup core
  28. * \brief File of class to offer components to list and upload files
  29. */
  30. /**
  31. * Class to offer components to list and upload files
  32. */
  33. class FormFile
  34. {
  35. private $db;
  36. /**
  37. * @var string Error code (or message)
  38. */
  39. public $error;
  40. public $numoffiles;
  41. public $infofiles; // Used to return informations by function getDocumentsLink
  42. /**
  43. * Constructor
  44. *
  45. * @param DoliDB $db Database handler
  46. */
  47. public function __construct($db)
  48. {
  49. $this->db = $db;
  50. $this->numoffiles = 0;
  51. }
  52. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  53. /**
  54. * Show form to upload a new file.
  55. *
  56. * @param string $url Url
  57. * @param string $title Title zone (Title or '' or 'none')
  58. * @param int $addcancel 1=Add 'Cancel' button
  59. * @param int $sectionid If upload must be done inside a particular ECM section (is sectionid defined, sectiondir must not be)
  60. * @param int $perm Value of permission to allow upload
  61. * @param int $size Length of input file area. Deprecated.
  62. * @param Object $object Object to use (when attachment is done on an element)
  63. * @param string $options Add an option column
  64. * @param integer $useajax Use fileupload ajax (0=never, 1=if enabled, 2=always whatever is option).
  65. * Deprecated 2 should never be used and if 1 is used, option should no be enabled.
  66. * @param string $savingdocmask Mask to use to define output filename. For example 'XXXXX-__YYYYMMDD__-__file__'
  67. * @param integer $linkfiles 1=Also add form to link files, 0=Do not show form to link files
  68. * @param string $htmlname Name and id of HTML form ('formuserfile' by default, 'formuserfileecm' when used to upload a file in ECM)
  69. * @param string $accept Specifies the types of files accepted (This is not a security check but an user interface facility. eg '.pdf,image/*' or '.png,.jpg' or 'video/*')
  70. * @param string $sectiondir If upload must be done inside a particular directory (if sectiondir defined, sectionid must not be)
  71. * @param int $usewithoutform 0=Default, 1=Disable <form> and <input hidden> to use in existing form area, 2=Disable the tag <form> only
  72. * @param int $capture 1=Add tag capture="capture" to force use of micro or video recording to generate file. When setting this to 1, you must also provide a value for $accept.
  73. * @param int $disablemulti 0=Default, 1=Disable multiple file upload
  74. * @param int $nooutput 0=Output result with print, 1=Return result
  75. * @return int|string <0 if KO, >0 if OK, or string if $noouput=1
  76. */
  77. public function form_attach_new_file($url, $title = '', $addcancel = 0, $sectionid = 0, $perm = 1, $size = 50, $object = '', $options = '', $useajax = 1, $savingdocmask = '', $linkfiles = 1, $htmlname = 'formuserfile', $accept = '', $sectiondir = '', $usewithoutform = 0, $capture = 0, $disablemulti = 0, $nooutput = 0)
  78. {
  79. // phpcs:enable
  80. global $conf, $langs, $hookmanager;
  81. $hookmanager->initHooks(array('formfile'));
  82. // Deprecation warning
  83. if ($useajax == 2) {
  84. dol_syslog(__METHOD__.": using 2 for useajax is deprecated and should be not used", LOG_WARNING);
  85. }
  86. if (!empty($conf->browser->layout) && $conf->browser->layout != 'classic') {
  87. $useajax = 0;
  88. }
  89. if ((!empty($conf->global->MAIN_USE_JQUERY_FILEUPLOAD) && $useajax) || ($useajax == 2)) {
  90. // TODO: Check this works with 2 forms on same page
  91. // TODO: Check this works with GED module, otherwise, force useajax to 0
  92. // TODO: This does not support option savingdocmask
  93. // TODO: This break feature to upload links too
  94. // TODO: Thisdoes not work when param nooutput=1
  95. return $this->_formAjaxFileUpload($object);
  96. } else {
  97. //If there is no permission and the option to hide unauthorized actions is enabled, then nothing is printed
  98. if (!$perm && !empty($conf->global->MAIN_BUTTON_HIDE_UNAUTHORIZED)) {
  99. if ($nooutput) {
  100. return '';
  101. } else {
  102. return 1;
  103. }
  104. }
  105. $out = "\n\n".'<!-- Start form attach new file --><div class="formattachnewfile">'."\n";
  106. if (empty($title)) {
  107. $title = $langs->trans("AttachANewFile");
  108. }
  109. if ($title != 'none') {
  110. $out .= load_fiche_titre($title, null, null);
  111. }
  112. if (empty($usewithoutform)) { // Try to avoid this and set instead the form by the caller.
  113. // Add a param as GET parameter to detect when POST were cleaned by PHP because a file larger than post_max_size
  114. $url .= (strpos($url, '?') === false ? '?' : '&').'uploadform=1';
  115. $out .= '<form name="'.$htmlname.'" id="'.$htmlname.'" action="'.$url.'" enctype="multipart/form-data" method="POST">'."\n";
  116. }
  117. if (empty($usewithoutform) || $usewithoutform == 2) {
  118. $out .= '<input type="hidden" name="token" value="'.newToken().'">'."\n";
  119. $out .= '<input type="hidden" id="'.$htmlname.'_section_dir" name="section_dir" value="'.$sectiondir.'">'."\n";
  120. $out .= '<input type="hidden" id="'.$htmlname.'_section_id" name="section_id" value="'.$sectionid.'">'."\n";
  121. $out .= '<input type="hidden" name="sortfield" value="'.GETPOST('sortfield', 'aZ09comma').'">'."\n";
  122. $out .= '<input type="hidden" name="sortorder" value="'.GETPOST('sortorder', 'aZ09comma').'">'."\n";
  123. $out .= '<input type="hidden" name="page_y" value="">'."\n";
  124. }
  125. $out .= '<table class="nobordernopadding centpercent">';
  126. $out .= '<tr>';
  127. if (!empty($options)) {
  128. $out .= '<td>'.$options.'</td>';
  129. }
  130. $out .= '<td class="valignmiddle nowrap">';
  131. $max = $conf->global->MAIN_UPLOAD_DOC; // In Kb
  132. $maxphp = @ini_get('upload_max_filesize'); // In unknown
  133. if (preg_match('/k$/i', $maxphp)) {
  134. $maxphp = preg_replace('/k$/i', '', $maxphp);
  135. $maxphp = $maxphp * 1;
  136. }
  137. if (preg_match('/m$/i', $maxphp)) {
  138. $maxphp = preg_replace('/m$/i', '', $maxphp);
  139. $maxphp = $maxphp * 1024;
  140. }
  141. if (preg_match('/g$/i', $maxphp)) {
  142. $maxphp = preg_replace('/g$/i', '', $maxphp);
  143. $maxphp = $maxphp * 1024 * 1024;
  144. }
  145. if (preg_match('/t$/i', $maxphp)) {
  146. $maxphp = preg_replace('/t$/i', '', $maxphp);
  147. $maxphp = $maxphp * 1024 * 1024 * 1024;
  148. }
  149. $maxphp2 = @ini_get('post_max_size'); // In unknown
  150. if (preg_match('/k$/i', $maxphp2)) {
  151. $maxphp2 = preg_replace('/k$/i', '', $maxphp2);
  152. $maxphp2 = $maxphp2 * 1;
  153. }
  154. if (preg_match('/m$/i', $maxphp2)) {
  155. $maxphp2 = preg_replace('/m$/i', '', $maxphp2);
  156. $maxphp2 = $maxphp2 * 1024;
  157. }
  158. if (preg_match('/g$/i', $maxphp2)) {
  159. $maxphp2 = preg_replace('/g$/i', '', $maxphp2);
  160. $maxphp2 = $maxphp2 * 1024 * 1024;
  161. }
  162. if (preg_match('/t$/i', $maxphp2)) {
  163. $maxphp2 = preg_replace('/t$/i', '', $maxphp2);
  164. $maxphp2 = $maxphp2 * 1024 * 1024 * 1024;
  165. }
  166. // Now $max and $maxphp and $maxphp2 are in Kb
  167. $maxmin = $max;
  168. $maxphptoshow = $maxphptoshowparam = '';
  169. if ($maxphp > 0) {
  170. $maxmin = min($max, $maxphp);
  171. $maxphptoshow = $maxphp;
  172. $maxphptoshowparam = 'upload_max_filesize';
  173. }
  174. if ($maxphp2 > 0) {
  175. $maxmin = min($max, $maxphp2);
  176. if ($maxphp2 < $maxphp) {
  177. $maxphptoshow = $maxphp2;
  178. $maxphptoshowparam = 'post_max_size';
  179. }
  180. }
  181. if ($maxmin > 0) {
  182. // MAX_FILE_SIZE doit précéder le champ input de type file
  183. $out .= '<input type="hidden" name="max_file_size" value="'.($maxmin * 1024).'">';
  184. }
  185. $out .= '<input class="flat minwidth400 maxwidth200onsmartphone" type="file"';
  186. //$out .= ((!empty($conf->global->MAIN_DISABLE_MULTIPLE_FILEUPLOAD) || $conf->browser->layout != 'classic') ? ' name="userfile"' : ' name="userfile[]" multiple');
  187. $out .= ((!empty($conf->global->MAIN_DISABLE_MULTIPLE_FILEUPLOAD) || $disablemulti) ? ' name="userfile"' : ' name="userfile[]" multiple');
  188. $out .= (empty($conf->global->MAIN_UPLOAD_DOC) || empty($perm) ? ' disabled' : '');
  189. $out .= (!empty($accept) ? ' accept="'.$accept.'"' : ' accept=""');
  190. $out .= (!empty($capture) ? ' capture="capture"' : '');
  191. $out .= '>';
  192. $out .= ' ';
  193. if ($sectionid) { // Show overwrite if exists for ECM module only
  194. $langs->load('link');
  195. $out .= '<span class="nowraponsmartphone"><input style="margin-right: 2px;" type="checkbox" id="overwritefile" name="overwritefile" value="1"><label for="overwritefile">'.$langs->trans("OverwriteIfExists").'</label></span>';
  196. }
  197. $out .= '<input type="submit" class="button small reposition" name="sendit" value="'.$langs->trans("Upload").'"';
  198. $out .= (empty($conf->global->MAIN_UPLOAD_DOC) || empty($perm) ? ' disabled' : '');
  199. $out .= '>';
  200. if ($addcancel) {
  201. $out .= ' &nbsp; ';
  202. $out .= '<input type="submit" class="button small button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
  203. }
  204. if (!empty($conf->global->MAIN_UPLOAD_DOC)) {
  205. if ($perm) {
  206. $menudolibarrsetupmax = $langs->transnoentitiesnoconv("Home").'-'.$langs->transnoentitiesnoconv("Setup").'-'.$langs->transnoentitiesnoconv("Security");
  207. $langs->load('other');
  208. $out .= ' ';
  209. $out .= info_admin($langs->trans("ThisLimitIsDefinedInSetupAt", $menudolibarrsetupmax, $max, $maxphptoshowparam, $maxphptoshow), 1);
  210. }
  211. } else {
  212. $out .= ' ('.$langs->trans("UploadDisabled").')';
  213. }
  214. $out .= "</td></tr>";
  215. if ($savingdocmask) {
  216. //add a global variable for disable the auto renaming on upload
  217. $rename = (empty($conf->global->MAIN_DOC_UPLOAD_NOT_RENAME_BY_DEFAULT) ? 'checked' : '');
  218. $out .= '<tr>';
  219. if (!empty($options)) {
  220. $out .= '<td>'.$options.'</td>';
  221. }
  222. $out .= '<td valign="middle" class="nowrap">';
  223. $out .= '<input type="checkbox" '.$rename.' class="savingdocmask" name="savingdocmask" id="savingdocmask" value="'.dol_escape_js($savingdocmask).'"> ';
  224. $out .= '<label class="opacitymedium small" for="savingdocmask">';
  225. $out .= $langs->trans("SaveUploadedFileWithMask", preg_replace('/__file__/', $langs->transnoentitiesnoconv("OriginFileName"), $savingdocmask), $langs->transnoentitiesnoconv("OriginFileName"));
  226. $out .= '</label>';
  227. $out .= '</td>';
  228. $out .= '</tr>';
  229. }
  230. $out .= "</table>";
  231. if (empty($usewithoutform)) {
  232. $out .= '</form>';
  233. if (empty($sectionid)) {
  234. $out .= '<br>';
  235. }
  236. }
  237. $out .= "\n</div><!-- End form attach new file -->\n";
  238. if ($linkfiles) {
  239. $out .= "\n".'<!-- Start form link new url --><div class="formlinknewurl">'."\n";
  240. $langs->load('link');
  241. $title = $langs->trans("LinkANewFile");
  242. $out .= load_fiche_titre($title, null, null);
  243. if (empty($usewithoutform)) {
  244. $out .= '<form name="'.$htmlname.'_link" id="'.$htmlname.'_link" action="'.$url.'" method="POST">'."\n";
  245. $out .= '<input type="hidden" name="token" value="'.newToken().'">'."\n";
  246. $out .= '<input type="hidden" id="'.$htmlname.'_link_section_dir" name="link_section_dir" value="">'."\n";
  247. $out .= '<input type="hidden" id="'.$htmlname.'_link_section_id" name="link_section_id" value="'.$sectionid.'">'."\n";
  248. $out .= '<input type="hidden" name="page_y" value="">'."\n";
  249. }
  250. $out .= '<div class="valignmiddle">';
  251. $out .= '<div class="inline-block" style="padding-right: 10px;">';
  252. if (!empty($conf->global->OPTIMIZEFORTEXTBROWSER)) {
  253. $out .= '<label for="link">'.$langs->trans("URLToLink").':</label> ';
  254. }
  255. $out .= '<input type="text" name="link" class="flat minwidth400imp" id="link" placeholder="'.dol_escape_htmltag($langs->trans("URLToLink")).'">';
  256. $out .= '</div>';
  257. $out .= '<div class="inline-block" style="padding-right: 10px;">';
  258. if (!empty($conf->global->OPTIMIZEFORTEXTBROWSER)) {
  259. $out .= '<label for="label">'.$langs->trans("Label").':</label> ';
  260. }
  261. $out .= '<input type="text" class="flat" name="label" id="label" placeholder="'.dol_escape_htmltag($langs->trans("Label")).'">';
  262. $out .= '<input type="hidden" name="objecttype" value="'.$object->element.'">';
  263. $out .= '<input type="hidden" name="objectid" value="'.$object->id.'">';
  264. $out .= '</div>';
  265. $out .= '<div class="inline-block" style="padding-right: 10px;">';
  266. $out .= '<input type="submit" class="button small reposition" name="linkit" value="'.$langs->trans("ToLink").'"';
  267. $out .= (empty($conf->global->MAIN_UPLOAD_DOC) || empty($perm) ? ' disabled' : '');
  268. $out .= '>';
  269. $out .= '</div>';
  270. $out .= '</div>';
  271. if (empty($usewithoutform)) {
  272. $out .= '<div class="clearboth"></div>';
  273. $out .= '</form><br>';
  274. }
  275. $out .= "\n</div><!-- End form link new url -->\n";
  276. }
  277. $parameters = array('socid'=>(isset($GLOBALS['socid']) ? $GLOBALS['socid'] : ''), 'id'=>(isset($GLOBALS['id']) ? $GLOBALS['id'] : ''), 'url'=>$url, 'perm'=>$perm, 'options'=>$options);
  278. $res = $hookmanager->executeHooks('formattachOptions', $parameters, $object);
  279. if (empty($res)) {
  280. $out = '<div class="'.($usewithoutform ? 'inline-block valignmiddle' : 'attacharea attacharea'.$htmlname).'">'.$out.'</div>';
  281. }
  282. $out .= $hookmanager->resPrint;
  283. if ($nooutput) {
  284. return $out;
  285. } else {
  286. print $out;
  287. return 1;
  288. }
  289. }
  290. }
  291. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  292. /**
  293. * Show the box with list of available documents for object
  294. *
  295. * @param string $modulepart propal, facture, facture_fourn, ...
  296. * @param string $modulesubdir Sub-directory to scan (Example: '0/1/10', 'FA/DD/MM/YY/9999'). Use '' if file is not into subdir of module.
  297. * @param string $filedir Directory to scan
  298. * @param string $urlsource Url of origin page (for return)
  299. * @param int $genallowed Generation is allowed (1/0 or array of formats)
  300. * @param int $delallowed Remove is allowed (1/0)
  301. * @param string $modelselected Model to preselect by default
  302. * @param integer $allowgenifempty Show warning if no model activated
  303. * @param integer $forcenomultilang Do not show language option (even if MAIN_MULTILANGS defined)
  304. * @param int $iconPDF Show only PDF icon with link (1/0)
  305. * @param int $notused Not used
  306. * @param integer $noform Do not output html form tags
  307. * @param string $param More param on http links
  308. * @param string $title Title to show on top of form
  309. * @param string $buttonlabel Label on submit button
  310. * @param string $codelang Default language code to use on lang combo box if multilang is enabled
  311. * @return int <0 if KO, number of shown files if OK
  312. * @deprecated Use print xxx->showdocuments() instead.
  313. */
  314. public function show_documents($modulepart, $modulesubdir, $filedir, $urlsource, $genallowed, $delallowed = 0, $modelselected = '', $allowgenifempty = 1, $forcenomultilang = 0, $iconPDF = 0, $notused = 0, $noform = 0, $param = '', $title = '', $buttonlabel = '', $codelang = '')
  315. {
  316. // phpcs:enable
  317. $this->numoffiles = 0;
  318. print $this->showdocuments($modulepart, $modulesubdir, $filedir, $urlsource, $genallowed, $delallowed, $modelselected, $allowgenifempty, $forcenomultilang, $iconPDF, $notused, $noform, $param, $title, $buttonlabel, $codelang);
  319. return $this->numoffiles;
  320. }
  321. /**
  322. * Return a string to show the box with list of available documents for object.
  323. * This also set the property $this->numoffiles
  324. *
  325. * @param string $modulepart Module the files are related to ('propal', 'facture', 'facture_fourn', 'mymodule', 'mymodule:MyObject', 'mymodule_temp', ...)
  326. * @param string $modulesubdir Existing (so sanitized) sub-directory to scan (Example: '0/1/10', 'FA/DD/MM/YY/9999'). Use '' if file is not into a subdir of module.
  327. * @param string $filedir Directory to scan (must not end with a /). Example: '/mydolibarrdocuments/facture/FAYYMM-1234'
  328. * @param string $urlsource Url of origin page (for return)
  329. * @param int|string[] $genallowed Generation is allowed (1/0 or array list of templates)
  330. * @param int $delallowed Remove is allowed (1/0)
  331. * @param string $modelselected Model to preselect by default
  332. * @param integer $allowgenifempty Allow generation even if list of template ($genallowed) is empty (show however a warning)
  333. * @param integer $forcenomultilang Do not show language option (even if MAIN_MULTILANGS defined)
  334. * @param int $iconPDF Deprecated, see getDocumentsLink
  335. * @param int $notused Not used
  336. * @param integer $noform Do not output html form tags
  337. * @param string $param More param on http links
  338. * @param string $title Title to show on top of form. Example: '' (Default to "Documents") or 'none'
  339. * @param string $buttonlabel Label on submit button
  340. * @param string $codelang Default language code to use on lang combo box if multilang is enabled
  341. * @param string $morepicto Add more HTML content into cell with picto
  342. * @param Object $object Object when method is called from an object card.
  343. * @param int $hideifempty Hide section of generated files if there is no file
  344. * @param string $removeaction (optional) The action to remove a file
  345. * @param string $tooltipontemplatecombo Text to show on a tooltip after the combo list of templates
  346. * @return string Output string with HTML array of documents (might be empty string)
  347. */
  348. public function showdocuments($modulepart, $modulesubdir, $filedir, $urlsource, $genallowed, $delallowed = 0, $modelselected = '', $allowgenifempty = 1, $forcenomultilang = 0, $iconPDF = 0, $notused = 0, $noform = 0, $param = '', $title = '', $buttonlabel = '', $codelang = '', $morepicto = '', $object = null, $hideifempty = 0, $removeaction = 'remove_file', $tooltipontemplatecombo = '')
  349. {
  350. global $dolibarr_main_url_root;
  351. // Deprecation warning
  352. if (!empty($iconPDF)) {
  353. dol_syslog(__METHOD__.": passing iconPDF parameter is deprecated", LOG_WARNING);
  354. }
  355. global $langs, $conf, $user, $hookmanager;
  356. global $form;
  357. $reshook = 0;
  358. if (is_object($hookmanager)) {
  359. $parameters = array(
  360. 'modulepart'=>&$modulepart,
  361. 'modulesubdir'=>&$modulesubdir,
  362. 'filedir'=>&$filedir,
  363. 'urlsource'=>&$urlsource,
  364. 'genallowed'=>&$genallowed,
  365. 'delallowed'=>&$delallowed,
  366. 'modelselected'=>&$modelselected,
  367. 'allowgenifempty'=>&$allowgenifempty,
  368. 'forcenomultilang'=>&$forcenomultilang,
  369. 'noform'=>&$noform,
  370. 'param'=>&$param,
  371. 'title'=>&$title,
  372. 'buttonlabel'=>&$buttonlabel,
  373. 'codelang'=>&$codelang,
  374. 'morepicto'=>&$morepicto,
  375. 'hideifempty'=>&$hideifempty,
  376. 'removeaction'=>&$removeaction
  377. );
  378. $reshook = $hookmanager->executeHooks('showDocuments', $parameters, $object); // Note that parameters may have been updated by hook
  379. // May report error
  380. if ($reshook < 0) {
  381. setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  382. }
  383. }
  384. // Remode default action if $reskook > 0
  385. if ($reshook > 0) {
  386. return $hookmanager->resPrint;
  387. }
  388. if (!is_object($form)) {
  389. $form = new Form($this->db);
  390. }
  391. include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  392. // For backward compatibility
  393. if (!empty($iconPDF)) {
  394. return $this->getDocumentsLink($modulepart, $modulesubdir, $filedir);
  395. }
  396. // Add entity in $param if not already exists
  397. if (!preg_match('/entity\=[0-9]+/', $param)) {
  398. $param .= ($param ? '&' : '').'entity='.(!empty($object->entity) ? $object->entity : $conf->entity);
  399. }
  400. $printer = 0;
  401. // The direct print feature is implemented only for such elements
  402. if (in_array($modulepart, array('contract', 'facture', 'supplier_proposal', 'propal', 'proposal', 'order', 'commande', 'expedition', 'commande_fournisseur', 'expensereport', 'delivery', 'ticket'))) {
  403. $printer = (!empty($user->rights->printing->read) && !empty($conf->printing->enabled)) ?true:false;
  404. }
  405. $hookmanager->initHooks(array('formfile'));
  406. // Get list of files
  407. $file_list = null;
  408. if (!empty($filedir)) {
  409. $file_list = dol_dir_list($filedir, 'files', 0, '', '(\.meta|_preview.*.*\.png)$', 'date', SORT_DESC);
  410. }
  411. if ($hideifempty && empty($file_list)) {
  412. return '';
  413. }
  414. $out = '';
  415. $forname = 'builddoc';
  416. $headershown = 0;
  417. $showempty = 0;
  418. $i = 0;
  419. $out .= "\n".'<!-- Start show_document -->'."\n";
  420. //print 'filedir='.$filedir;
  421. if (preg_match('/massfilesarea_/', $modulepart)) {
  422. $out .= '<div id="show_files"><br></div>'."\n";
  423. $title = $langs->trans("MassFilesArea").' <a href="" id="togglemassfilesarea" ref="shown">('.$langs->trans("Hide").')</a>';
  424. $title .= '<script>
  425. jQuery(document).ready(function() {
  426. jQuery(\'#togglemassfilesarea\').click(function() {
  427. if (jQuery(\'#togglemassfilesarea\').attr(\'ref\') == "shown")
  428. {
  429. jQuery(\'#'.$modulepart.'_table\').hide();
  430. jQuery(\'#togglemassfilesarea\').attr("ref", "hidden");
  431. jQuery(\'#togglemassfilesarea\').text("('.dol_escape_js($langs->trans("Show")).')");
  432. }
  433. else
  434. {
  435. jQuery(\'#'.$modulepart.'_table\').show();
  436. jQuery(\'#togglemassfilesarea\').attr("ref","shown");
  437. jQuery(\'#togglemassfilesarea\').text("('.dol_escape_js($langs->trans("Hide")).')");
  438. }
  439. return false;
  440. });
  441. });
  442. </script>';
  443. }
  444. $titletoshow = $langs->trans("Documents");
  445. if (!empty($title)) {
  446. $titletoshow = ($title == 'none' ? '' : $title);
  447. }
  448. // Show table
  449. if ($genallowed) {
  450. $modellist = array();
  451. if ($modulepart == 'company') {
  452. $showempty = 1; // can have no template active
  453. if (is_array($genallowed)) {
  454. $modellist = $genallowed;
  455. } else {
  456. include_once DOL_DOCUMENT_ROOT.'/core/modules/societe/modules_societe.class.php';
  457. $modellist = ModeleThirdPartyDoc::liste_modeles($this->db);
  458. }
  459. } elseif ($modulepart == 'propal') {
  460. if (is_array($genallowed)) {
  461. $modellist = $genallowed;
  462. } else {
  463. include_once DOL_DOCUMENT_ROOT.'/core/modules/propale/modules_propale.php';
  464. $modellist = ModelePDFPropales::liste_modeles($this->db);
  465. }
  466. } elseif ($modulepart == 'supplier_proposal') {
  467. if (is_array($genallowed)) {
  468. $modellist = $genallowed;
  469. } else {
  470. include_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_proposal/modules_supplier_proposal.php';
  471. $modellist = ModelePDFSupplierProposal::liste_modeles($this->db);
  472. }
  473. } elseif ($modulepart == 'commande') {
  474. if (is_array($genallowed)) {
  475. $modellist = $genallowed;
  476. } else {
  477. include_once DOL_DOCUMENT_ROOT.'/core/modules/commande/modules_commande.php';
  478. $modellist = ModelePDFCommandes::liste_modeles($this->db);
  479. }
  480. } elseif ($modulepart == 'expedition') {
  481. if (is_array($genallowed)) {
  482. $modellist = $genallowed;
  483. } else {
  484. include_once DOL_DOCUMENT_ROOT.'/core/modules/expedition/modules_expedition.php';
  485. $modellist = ModelePDFExpedition::liste_modeles($this->db);
  486. }
  487. } elseif ($modulepart == 'reception') {
  488. if (is_array($genallowed)) {
  489. $modellist = $genallowed;
  490. } else {
  491. include_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
  492. $modellist = ModelePdfReception::liste_modeles($this->db);
  493. }
  494. } elseif ($modulepart == 'delivery') {
  495. if (is_array($genallowed)) {
  496. $modellist = $genallowed;
  497. } else {
  498. include_once DOL_DOCUMENT_ROOT.'/core/modules/delivery/modules_delivery.php';
  499. $modellist = ModelePDFDeliveryOrder::liste_modeles($this->db);
  500. }
  501. } elseif ($modulepart == 'ficheinter') {
  502. if (is_array($genallowed)) {
  503. $modellist = $genallowed;
  504. } else {
  505. include_once DOL_DOCUMENT_ROOT.'/core/modules/fichinter/modules_fichinter.php';
  506. $modellist = ModelePDFFicheinter::liste_modeles($this->db);
  507. }
  508. } elseif ($modulepart == 'facture') {
  509. if (is_array($genallowed)) {
  510. $modellist = $genallowed;
  511. } else {
  512. include_once DOL_DOCUMENT_ROOT.'/core/modules/facture/modules_facture.php';
  513. $modellist = ModelePDFFactures::liste_modeles($this->db);
  514. }
  515. } elseif ($modulepart == 'contract') {
  516. $showempty = 1; // can have no template active
  517. if (is_array($genallowed)) {
  518. $modellist = $genallowed;
  519. } else {
  520. include_once DOL_DOCUMENT_ROOT.'/core/modules/contract/modules_contract.php';
  521. $modellist = ModelePDFContract::liste_modeles($this->db);
  522. }
  523. } elseif ($modulepart == 'project') {
  524. if (is_array($genallowed)) {
  525. $modellist = $genallowed;
  526. } else {
  527. include_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php';
  528. $modellist = ModelePDFProjects::liste_modeles($this->db);
  529. }
  530. } elseif ($modulepart == 'project_task') {
  531. if (is_array($genallowed)) {
  532. $modellist = $genallowed;
  533. } else {
  534. include_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/modules_task.php';
  535. $modellist = ModelePDFTask::liste_modeles($this->db);
  536. }
  537. } elseif ($modulepart == 'product') {
  538. if (is_array($genallowed)) {
  539. $modellist = $genallowed;
  540. } else {
  541. include_once DOL_DOCUMENT_ROOT.'/core/modules/product/modules_product.class.php';
  542. $modellist = ModelePDFProduct::liste_modeles($this->db);
  543. }
  544. } elseif ($modulepart == 'product_batch') {
  545. if (is_array($genallowed)) {
  546. $modellist = $genallowed;
  547. } else {
  548. include_once DOL_DOCUMENT_ROOT.'/core/modules/product_batch/modules_product_batch.class.php';
  549. $modellist = ModelePDFProductBatch::liste_modeles($this->db);
  550. }
  551. } elseif ($modulepart == 'stock') {
  552. if (is_array($genallowed)) {
  553. $modellist = $genallowed;
  554. } else {
  555. include_once DOL_DOCUMENT_ROOT.'/core/modules/stock/modules_stock.php';
  556. $modellist = ModelePDFStock::liste_modeles($this->db);
  557. }
  558. } elseif ($modulepart == 'movement') {
  559. if (is_array($genallowed)) {
  560. $modellist = $genallowed;
  561. } else {
  562. include_once DOL_DOCUMENT_ROOT.'/core/modules/stock/modules_movement.php';
  563. $modellist = ModelePDFMovement::liste_modeles($this->db);
  564. }
  565. } elseif ($modulepart == 'export') {
  566. if (is_array($genallowed)) {
  567. $modellist = $genallowed;
  568. } else {
  569. include_once DOL_DOCUMENT_ROOT.'/core/modules/export/modules_export.php';
  570. $modellist = ModeleExports::liste_modeles($this->db);
  571. }
  572. } elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') {
  573. if (is_array($genallowed)) {
  574. $modellist = $genallowed;
  575. } else {
  576. include_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_order/modules_commandefournisseur.php';
  577. $modellist = ModelePDFSuppliersOrders::liste_modeles($this->db);
  578. }
  579. } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'supplier_invoice') {
  580. $showempty = 1; // can have no template active
  581. if (is_array($genallowed)) {
  582. $modellist = $genallowed;
  583. } else {
  584. include_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_invoice/modules_facturefournisseur.php';
  585. $modellist = ModelePDFSuppliersInvoices::liste_modeles($this->db);
  586. }
  587. } elseif ($modulepart == 'supplier_payment') {
  588. if (is_array($genallowed)) {
  589. $modellist = $genallowed;
  590. } else {
  591. include_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_payment/modules_supplier_payment.php';
  592. $modellist = ModelePDFSuppliersPayments::liste_modeles($this->db);
  593. }
  594. } elseif ($modulepart == 'remisecheque') {
  595. if (is_array($genallowed)) {
  596. $modellist = $genallowed;
  597. } else {
  598. include_once DOL_DOCUMENT_ROOT.'/core/modules/cheque/modules_chequereceipts.php';
  599. $modellist = ModeleChequeReceipts::liste_modeles($this->db);
  600. }
  601. } elseif ($modulepart == 'donation') {
  602. if (is_array($genallowed)) {
  603. $modellist = $genallowed;
  604. } else {
  605. include_once DOL_DOCUMENT_ROOT.'/core/modules/dons/modules_don.php';
  606. $modellist = ModeleDon::liste_modeles($this->db);
  607. }
  608. } elseif ($modulepart == 'member') {
  609. if (is_array($genallowed)) {
  610. $modellist = $genallowed;
  611. } else {
  612. include_once DOL_DOCUMENT_ROOT.'/core/modules/member/modules_cards.php';
  613. $modellist = ModelePDFCards::liste_modeles($this->db);
  614. }
  615. } elseif ($modulepart == 'agenda' || $modulepart == 'actions') {
  616. if (is_array($genallowed)) {
  617. $modellist = $genallowed;
  618. } else {
  619. include_once DOL_DOCUMENT_ROOT.'/core/modules/action/modules_action.php';
  620. $modellist = ModeleAction::liste_modeles($this->db);
  621. }
  622. } elseif ($modulepart == 'expensereport') {
  623. if (is_array($genallowed)) {
  624. $modellist = $genallowed;
  625. } else {
  626. include_once DOL_DOCUMENT_ROOT.'/core/modules/expensereport/modules_expensereport.php';
  627. $modellist = ModeleExpenseReport::liste_modeles($this->db);
  628. }
  629. } elseif ($modulepart == 'unpaid') {
  630. $modellist = '';
  631. } elseif ($modulepart == 'user') {
  632. if (is_array($genallowed)) {
  633. $modellist = $genallowed;
  634. } else {
  635. include_once DOL_DOCUMENT_ROOT.'/core/modules/user/modules_user.class.php';
  636. $modellist = ModelePDFUser::liste_modeles($this->db);
  637. }
  638. } elseif ($modulepart == 'usergroup') {
  639. if (is_array($genallowed)) {
  640. $modellist = $genallowed;
  641. } else {
  642. include_once DOL_DOCUMENT_ROOT.'/core/modules/usergroup/modules_usergroup.class.php';
  643. $modellist = ModelePDFUserGroup::liste_modeles($this->db);
  644. }
  645. } else {
  646. $submodulepart = $modulepart;
  647. // modulepart = 'nameofmodule' or 'nameofmodule:NameOfObject'
  648. $tmp = explode(':', $modulepart);
  649. if (!empty($tmp[1])) {
  650. $modulepart = $tmp[0];
  651. $submodulepart = $tmp[1];
  652. }
  653. // For normalized standard modules
  654. $file = dol_buildpath('/core/modules/'.$modulepart.'/modules_'.strtolower($submodulepart).'.php', 0);
  655. if (file_exists($file)) {
  656. $res = include_once $file;
  657. } else {
  658. // For normalized external modules.
  659. $file = dol_buildpath('/'.$modulepart.'/core/modules/'.$modulepart.'/modules_'.strtolower($submodulepart).'.php', 0);
  660. $res = include_once $file;
  661. }
  662. $class = 'ModelePDF'.ucfirst($submodulepart);
  663. if (class_exists($class)) {
  664. $modellist = call_user_func($class.'::liste_modeles', $this->db);
  665. } else {
  666. dol_print_error($this->db, "Bad value for modulepart '".$modulepart."' in showdocuments (class ".$class." for Doc generation not found)");
  667. return -1;
  668. }
  669. }
  670. // Set headershown to avoid to have table opened a second time later
  671. $headershown = 1;
  672. if (empty($buttonlabel)) {
  673. $buttonlabel = $langs->trans('Generate');
  674. }
  675. if ($conf->browser->layout == 'phone') {
  676. $urlsource .= '#'.$forname.'_form'; // So we switch to form after a generation
  677. }
  678. if (empty($noform)) {
  679. $out .= '<form action="'.$urlsource.'" id="'.$forname.'_form" method="post">';
  680. }
  681. $out .= '<input type="hidden" name="action" value="builddoc">';
  682. $out .= '<input type="hidden" name="page_y" value="">';
  683. $out .= '<input type="hidden" name="token" value="'.newToken().'">';
  684. $out .= load_fiche_titre($titletoshow, '', '');
  685. $out .= '<div class="div-table-responsive-no-min">';
  686. $out .= '<table class="liste formdoc noborder centpercent">';
  687. $out .= '<tr class="liste_titre">';
  688. $addcolumforpicto = ($delallowed || $printer || $morepicto);
  689. $colspan = (4 + ($addcolumforpicto ? 1 : 0));
  690. $colspanmore = 0;
  691. $out .= '<th colspan="'.$colspan.'" class="formdoc liste_titre maxwidthonsmartphone center">';
  692. // Model
  693. if (!empty($modellist)) {
  694. asort($modellist);
  695. $out .= '<span class="hideonsmartphone">'.$langs->trans('Model').' </span>';
  696. if (is_array($modellist) && count($modellist) == 1) { // If there is only one element
  697. $arraykeys = array_keys($modellist);
  698. $modelselected = $arraykeys[0];
  699. }
  700. $morecss = 'minwidth75 maxwidth200';
  701. if ($conf->browser->layout == 'phone') {
  702. $morecss = 'maxwidth100';
  703. }
  704. $out .= $form->selectarray('model', $modellist, $modelselected, $showempty, 0, 0, '', 0, 0, 0, '', $morecss);
  705. if ($conf->use_javascript_ajax) {
  706. $out .= ajax_combobox('model');
  707. }
  708. $out .= $form->textwithpicto('', $tooltipontemplatecombo, 1, 'help', 'marginrightonly', 0, 3, '', 0);
  709. } else {
  710. $out .= '<div class="float">'.$langs->trans("Files").'</div>';
  711. }
  712. // Language code (if multilang)
  713. if (($allowgenifempty || (is_array($modellist) && count($modellist) > 0)) && !empty($conf->global->MAIN_MULTILANGS) && !$forcenomultilang && (!empty($modellist) || $showempty)) {
  714. include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
  715. $formadmin = new FormAdmin($this->db);
  716. $defaultlang = ($codelang && $codelang != 'auto') ? $codelang : $langs->getDefaultLang();
  717. $morecss = 'maxwidth150';
  718. if ($conf->browser->layout == 'phone') {
  719. $morecss = 'maxwidth100';
  720. }
  721. $out .= $formadmin->select_language($defaultlang, 'lang_id', 0, null, 0, 0, 0, $morecss);
  722. } else {
  723. $out .= '&nbsp;';
  724. }
  725. // Button
  726. $genbutton = '<input class="button buttongen reposition nomargintop nomarginbottom" id="'.$forname.'_generatebutton" name="'.$forname.'_generatebutton"';
  727. $genbutton .= ' type="submit" value="'.$buttonlabel.'"';
  728. if (!$allowgenifempty && !is_array($modellist) && empty($modellist)) {
  729. $genbutton .= ' disabled';
  730. }
  731. $genbutton .= '>';
  732. if ($allowgenifempty && !is_array($modellist) && empty($modellist) && empty($conf->dol_no_mouse_hover) && $modulepart != 'unpaid') {
  733. $langs->load("errors");
  734. $genbutton .= ' '.img_warning($langs->transnoentitiesnoconv("WarningNoDocumentModelActivated"));
  735. }
  736. if (!$allowgenifempty && !is_array($modellist) && empty($modellist) && empty($conf->dol_no_mouse_hover) && $modulepart != 'unpaid') {
  737. $genbutton = '';
  738. }
  739. if (empty($modellist) && !$showempty && $modulepart != 'unpaid') {
  740. $genbutton = '';
  741. }
  742. $out .= $genbutton;
  743. $out .= '</th>';
  744. if (!empty($hookmanager->hooks['formfile'])) {
  745. foreach ($hookmanager->hooks['formfile'] as $module) {
  746. if (method_exists($module, 'formBuilddocLineOptions')) {
  747. $colspanmore++;
  748. $out .= '<th></th>';
  749. }
  750. }
  751. }
  752. $out .= '</tr>';
  753. // Execute hooks
  754. $parameters = array('colspan'=>($colspan + $colspanmore), 'socid'=>(isset($GLOBALS['socid']) ? $GLOBALS['socid'] : ''), 'id'=>(isset($GLOBALS['id']) ? $GLOBALS['id'] : ''), 'modulepart'=>$modulepart);
  755. if (is_object($hookmanager)) {
  756. $reshook = $hookmanager->executeHooks('formBuilddocOptions', $parameters, $GLOBALS['object']);
  757. $out .= $hookmanager->resPrint;
  758. }
  759. }
  760. // Get list of files
  761. if (!empty($filedir)) {
  762. $link_list = array();
  763. if (is_object($object)) {
  764. require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
  765. $link = new Link($this->db);
  766. $sortfield = $sortorder = null;
  767. $res = $link->fetchAll($link_list, $object->element, $object->id, $sortfield, $sortorder);
  768. }
  769. $out .= '<!-- html.formfile::showdocuments -->'."\n";
  770. // Show title of array if not already shown
  771. if ((!empty($file_list) || !empty($link_list) || preg_match('/^massfilesarea/', $modulepart))
  772. && !$headershown) {
  773. $headershown = 1;
  774. $out .= '<div class="titre">'.$titletoshow.'</div>'."\n";
  775. $out .= '<div class="div-table-responsive-no-min">';
  776. $out .= '<table class="noborder centpercent" id="'.$modulepart.'_table">'."\n";
  777. }
  778. // Loop on each file found
  779. if (is_array($file_list)) {
  780. // Defined relative dir to DOL_DATA_ROOT
  781. $relativedir = '';
  782. if ($filedir) {
  783. $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filedir);
  784. $relativedir = preg_replace('/^[\\/]/', '', $relativedir);
  785. }
  786. // Get list of files stored into database for same relative directory
  787. if ($relativedir) {
  788. completeFileArrayWithDatabaseInfo($file_list, $relativedir);
  789. //var_dump($sortfield.' - '.$sortorder);
  790. if (!empty($sortfield) && !empty($sortorder)) { // If $sortfield is for example 'position_name', we will sort on the property 'position_name' (that is concat of position+name)
  791. $file_list = dol_sort_array($file_list, $sortfield, $sortorder);
  792. }
  793. }
  794. foreach ($file_list as $file) {
  795. // Define relative path for download link (depends on module)
  796. $relativepath = $file["name"]; // Cas general
  797. if ($modulesubdir) {
  798. $relativepath = $modulesubdir."/".$file["name"]; // Cas propal, facture...
  799. }
  800. if ($modulepart == 'export') {
  801. $relativepath = $file["name"]; // Other case
  802. }
  803. $out .= '<tr class="oddeven">';
  804. $documenturl = DOL_URL_ROOT.'/document.php';
  805. if (isset($conf->global->DOL_URL_ROOT_DOCUMENT_PHP)) {
  806. $documenturl = $conf->global->DOL_URL_ROOT_DOCUMENT_PHP; // To use another wrapper
  807. }
  808. // Show file name with link to download
  809. $out .= '<td class="minwidth200 tdoverflowmax300">';
  810. $out .= '<a class="documentdownload paddingright" href="'.$documenturl.'?modulepart='.$modulepart.'&amp;file='.urlencode($relativepath).($param ? '&'.$param : '').'"';
  811. $mime = dol_mimetype($relativepath, '', 0);
  812. if (preg_match('/text/', $mime)) {
  813. $out .= ' target="_blank" rel="noopener noreferrer"';
  814. }
  815. $out .= '>';
  816. $out .= img_mime($file["name"], $langs->trans("File").': '.$file["name"]);
  817. $out .= dol_trunc($file["name"], 40);
  818. $out .= '</a>'."\n";
  819. $out .= $this->showPreview($file, $modulepart, $relativepath, 0, $param);
  820. $out .= '</td>';
  821. // Show file size
  822. $size = (!empty($file['size']) ? $file['size'] : dol_filesize($filedir."/".$file["name"]));
  823. $out .= '<td class="nowraponall right">'.dol_print_size($size, 1, 1).'</td>';
  824. // Show file date
  825. $date = (!empty($file['date']) ? $file['date'] : dol_filemtime($filedir."/".$file["name"]));
  826. $out .= '<td class="nowrap right">'.dol_print_date($date, 'dayhour', 'tzuser').'</td>';
  827. // Show share link
  828. $out .= '<td class="nowraponall">';
  829. if (!empty($file['share'])) {
  830. // Define $urlwithroot
  831. $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
  832. $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
  833. //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
  834. //print '<span class="opacitymedium">'.$langs->trans("Hash").' : '.$file['share'].'</span>';
  835. $forcedownload = 0;
  836. $paramlink = '';
  837. if (!empty($file['share'])) {
  838. $paramlink .= ($paramlink ? '&' : '').'hashp='.$file['share']; // Hash for public share
  839. }
  840. if ($forcedownload) {
  841. $paramlink .= ($paramlink ? '&' : '').'attachment=1';
  842. }
  843. $fulllink = $urlwithroot.'/document.php'.($paramlink ? '?'.$paramlink : '');
  844. $out .= img_picto($langs->trans("FileSharedViaALink"), 'globe').' ';
  845. $out .= '<input type="text" class="quatrevingtpercentminusx width75 nopadding small" id="downloadlink'.$file['rowid'].'" name="downloadexternallink" title="'.dol_escape_htmltag($langs->trans("FileSharedViaALink")).'" value="'.dol_escape_htmltag($fulllink).'">';
  846. $out .= ajax_autoselect('downloadlink'.$file['rowid']);
  847. } else {
  848. //print '<span class="opacitymedium">'.$langs->trans("FileNotShared").'</span>';
  849. }
  850. $out .= '</td>';
  851. // Show picto delete, print...
  852. if ($delallowed || $printer || $morepicto) {
  853. $out .= '<td class="right nowraponall">';
  854. if ($delallowed) {
  855. $tmpurlsource = preg_replace('/#[a-zA-Z0-9_]*$/', '', $urlsource);
  856. $out .= '<a class="reposition" href="'.$tmpurlsource.((strpos($tmpurlsource, '?') === false) ? '?' : '&').'action='.urlencode($removeaction).'&token='.newToken().'&file='.urlencode($relativepath);
  857. $out .= ($param ? '&'.$param : '');
  858. //$out.= '&modulepart='.$modulepart; // TODO obsolete ?
  859. //$out.= '&urlsource='.urlencode($urlsource); // TODO obsolete ?
  860. $out .= '">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
  861. }
  862. if ($printer) {
  863. $out .= '<a class="marginleftonly reposition" href="'.$urlsource.(strpos($urlsource, '?') ? '&' : '?').'action=print_file&token='.newToken().'&printer='.urlencode($modulepart).'&file='.urlencode($relativepath);
  864. $out .= ($param ? '&'.$param : '');
  865. $out .= '">'.img_picto($langs->trans("PrintFile", $relativepath), 'printer.png').'</a>';
  866. }
  867. if ($morepicto) {
  868. $morepicto = preg_replace('/__FILENAMEURLENCODED__/', urlencode($relativepath), $morepicto);
  869. $out .= $morepicto;
  870. }
  871. $out .= '</td>';
  872. }
  873. if (is_object($hookmanager)) {
  874. $parameters = array('colspan'=>($colspan + $colspanmore), 'socid'=>(isset($GLOBALS['socid']) ? $GLOBALS['socid'] : ''), 'id'=>(isset($GLOBALS['id']) ? $GLOBALS['id'] : ''), 'modulepart'=>$modulepart, 'relativepath'=>$relativepath);
  875. $res = $hookmanager->executeHooks('formBuilddocLineOptions', $parameters, $file);
  876. if (empty($res)) {
  877. $out .= $hookmanager->resPrint; // Complete line
  878. $out .= '</tr>';
  879. } else {
  880. $out = $hookmanager->resPrint; // Replace all $out
  881. }
  882. }
  883. }
  884. $this->numoffiles++;
  885. }
  886. // Loop on each link found
  887. if (is_array($link_list)) {
  888. $colspan = 2;
  889. foreach ($link_list as $file) {
  890. $out .= '<tr class="oddeven">';
  891. $out .= '<td colspan="'.$colspan.'" class="maxwidhtonsmartphone">';
  892. $out .= '<a data-ajax="false" href="'.$file->url.'" target="_blank" rel="noopener noreferrer">';
  893. $out .= $file->label;
  894. $out .= '</a>';
  895. $out .= '</td>';
  896. $out .= '<td class="right">';
  897. $out .= dol_print_date($file->datea, 'dayhour');
  898. $out .= '</td>';
  899. // for share link of files
  900. $out .= '<td></td>';
  901. if ($delallowed || $printer || $morepicto) {
  902. $out .= '<td></td>';
  903. }
  904. $out .= '</tr>'."\n";
  905. }
  906. $this->numoffiles++;
  907. }
  908. if (count($file_list) == 0 && count($link_list) == 0 && $headershown) {
  909. $out .= '<tr><td colspan="'.(3 + ($addcolumforpicto ? 1 : 0)).'"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>'."\n";
  910. }
  911. }
  912. if ($headershown) {
  913. // Affiche pied du tableau
  914. $out .= "</table>\n";
  915. $out .= "</div>\n";
  916. if ($genallowed) {
  917. if (empty($noform)) {
  918. $out .= '</form>'."\n";
  919. }
  920. }
  921. }
  922. $out .= '<!-- End show_document -->'."\n";
  923. //return ($i?$i:$headershown);
  924. return $out;
  925. }
  926. /**
  927. * Show a Document icon with link(s)
  928. * You may want to call this into a div like this:
  929. * print '<div class="inline-block valignmiddle">'.$formfile->getDocumentsLink($element_doc, $filename, $filedir).'</div>';
  930. *
  931. * @param string $modulepart 'propal', 'facture', 'facture_fourn', ...
  932. * @param string $modulesubdir Sub-directory to scan (Example: '0/1/10', 'FA/DD/MM/YY/9999'). Use '' if file is not into subdir of module.
  933. * @param string $filedir Full path to directory to scan
  934. * @param string $filter Filter filenames on this regex string (Example: '\.pdf$')
  935. * @param string $morecss Add more css to the download picto
  936. * @param string $allfiles 0=Only generated docs, 1=All files
  937. * @return string Output string with HTML link of documents (might be empty string). This also fill the array ->infofiles
  938. */
  939. public function getDocumentsLink($modulepart, $modulesubdir, $filedir, $filter = '', $morecss = 'valignmiddle', $allfiles = 0)
  940. {
  941. global $conf, $langs;
  942. include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  943. $out = '';
  944. $this->infofiles = array('nboffiles'=>0, 'extensions'=>array(), 'files'=>array());
  945. $entity = 1; // Without multicompany
  946. // Get object entity
  947. if (!empty($conf->multicompany->enabled)) {
  948. $regs = array();
  949. preg_match('/\/([0-9]+)\/[^\/]+\/'.preg_quote($modulesubdir, '/').'$/', $filedir, $regs);
  950. $entity = ((!empty($regs[1]) && $regs[1] > 1) ? $regs[1] : 1); // If entity id not found in $filedir this is entity 1 by default
  951. }
  952. // Get list of files starting with name of ref (Note: files with '^ref\.extension' are generated files, files with '^ref-...' are uploaded files)
  953. if ($allfiles || !empty($conf->global->MAIN_SHOW_ALL_FILES_ON_DOCUMENT_TOOLTIP)) {
  954. $filterforfilesearch = '^'.preg_quote(basename($modulesubdir), '/');
  955. } else {
  956. $filterforfilesearch = '^'.preg_quote(basename($modulesubdir), '/').'\.';
  957. }
  958. $file_list = dol_dir_list($filedir, 'files', 0, $filterforfilesearch, '\.meta$|\.png$'); // We also discard .meta and .png preview
  959. //var_dump($file_list);
  960. // For ajax treatment
  961. $out .= '<!-- html.formfile::getDocumentsLink -->'."\n";
  962. if (!empty($file_list)) {
  963. $out = '<dl class="dropdown inline-block">
  964. <dt><a data-ajax="false" href="#" onClick="return false;">'.img_picto('', 'listlight', '', 0, 0, 0, '', $morecss).'</a></dt>
  965. <dd><div class="multichoicedoc" style="position:absolute;left:100px;" ><ul class="ulselectedfields">';
  966. $tmpout = '';
  967. // Loop on each file found
  968. $found = 0;
  969. $i = 0;
  970. foreach ($file_list as $file) {
  971. $i++;
  972. if ($filter && !preg_match('/'.$filter.'/i', $file["name"])) {
  973. continue; // Discard this. It does not match provided filter.
  974. }
  975. $found++;
  976. // Define relative path for download link (depends on module)
  977. $relativepath = $file["name"]; // Cas general
  978. if ($modulesubdir) {
  979. $relativepath = $modulesubdir."/".$file["name"]; // Cas propal, facture...
  980. }
  981. // Autre cas
  982. if ($modulepart == 'donation') {
  983. $relativepath = get_exdir($modulesubdir, 2, 0, 0, null, 'donation').$file["name"];
  984. }
  985. if ($modulepart == 'export') {
  986. $relativepath = $file["name"];
  987. }
  988. $this->infofiles['nboffiles']++;
  989. $this->infofiles['files'][] = $file['fullname'];
  990. $ext = pathinfo($file["name"], PATHINFO_EXTENSION);
  991. if (empty($this->infofiles[$ext])) {
  992. $this->infofiles['extensions'][$ext] = 1;
  993. } else {
  994. $this->infofiles['extensions'][$ext]++;
  995. }
  996. // Preview
  997. if (!empty($conf->use_javascript_ajax) && ($conf->browser->layout != 'phone')) {
  998. $tmparray = getAdvancedPreviewUrl($modulepart, $relativepath, 1, '&entity='.$entity);
  999. if ($tmparray && $tmparray['url']) {
  1000. $tmpout .= '<li><a href="'.$tmparray['url'].'"'.($tmparray['css'] ? ' class="'.$tmparray['css'].'"' : '').($tmparray['mime'] ? ' mime="'.$tmparray['mime'].'"' : '').($tmparray['target'] ? ' target="'.$tmparray['target'].'"' : '').'>';
  1001. //$tmpout.= img_picto('','detail');
  1002. $tmpout .= '<i class="fa fa-search-plus paddingright" style="color: gray"></i>';
  1003. $tmpout .= $langs->trans("Preview").' '.$ext.'</a></li>';
  1004. }
  1005. }
  1006. // Download
  1007. $tmpout .= '<li class="nowrap"><a class="pictopreview nowrap" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&amp;entity='.$entity.'&amp;file='.urlencode($relativepath).'"';
  1008. $mime = dol_mimetype($relativepath, '', 0);
  1009. if (preg_match('/text/', $mime)) {
  1010. $tmpout .= ' target="_blank" rel="noopener noreferrer"';
  1011. }
  1012. $tmpout .= '>';
  1013. $tmpout .= img_mime($relativepath, $file["name"]);
  1014. $tmpout .= $langs->trans("Download").' '.$ext;
  1015. $tmpout .= '</a></li>'."\n";
  1016. }
  1017. $out .= $tmpout;
  1018. $out .= '</ul></div></dd>
  1019. </dl>';
  1020. if (!$found) {
  1021. $out = '';
  1022. }
  1023. } else {
  1024. // TODO Add link to regenerate doc ?
  1025. //$out.= '<div id="gen_pdf_'.$modulesubdir.'" class="linkobject hideobject">'.img_picto('', 'refresh').'</div>'."\n";
  1026. }
  1027. return $out;
  1028. }
  1029. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  1030. /**
  1031. * Show list of documents in $filearray (may be they are all in same directory but may not)
  1032. * This also sync database if $upload_dir is defined.
  1033. *
  1034. * @param array $filearray Array of files loaded by dol_dir_list('files') function before calling this.
  1035. * @param Object $object Object on which document is linked to.
  1036. * @param string $modulepart Value for modulepart used by download or viewimage wrapper.
  1037. * @param string $param Parameters on sort links (param must start with &, example &aaa=bbb&ccc=ddd)
  1038. * @param int $forcedownload Force to open dialog box "Save As" when clicking on file.
  1039. * @param string $relativepath Relative path of docs (autodefined if not provided), relative to module dir, not to MAIN_DATA_ROOT.
  1040. * @param int $permonobject Permission on object (so permission to delete or crop document)
  1041. * @param int $useinecm Change output for use in ecm module:
  1042. * 0 or 6: Add a preview column. Show also a rename button. Show also a crop button for some values of $modulepart (must be supported into hard coded list in this function + photos_resize.php + restrictedArea + checkUserAccessToObject)
  1043. * 1: Add link to edit ECM entry
  1044. * 2: Add rename and crop link
  1045. * 4: Add a preview column
  1046. * 5: Add link to edit ECM entry and Add a preview column
  1047. * @param string $textifempty Text to show if filearray is empty ('NoFileFound' if not defined)
  1048. * @param int $maxlength Maximum length of file name shown.
  1049. * @param string $title Title before list. Use 'none' to disable title.
  1050. * @param string $url Full url to use for click links ('' = autodetect)
  1051. * @param int $showrelpart 0=Show only filename (default), 1=Show first level 1 dir
  1052. * @param int $permtoeditline Permission to edit document line (You must provide a value, -1 is deprecated and must not be used any more)
  1053. * @param string $upload_dir Full path directory so we can know dir relative to MAIN_DATA_ROOT. Fill this to complete file data with database indexes.
  1054. * @param string $sortfield Sort field ('name', 'size', 'position', ...)
  1055. * @param string $sortorder Sort order ('ASC' or 'DESC')
  1056. * @param int $disablemove 1=Disable move button, 0=Position move is possible.
  1057. * @param int $addfilterfields Add line with filters
  1058. * @param int $disablecrop Disable crop feature on images (-1 = auto, prefer to set it explicitely to 0 or 1)
  1059. * @return int <0 if KO, nb of files shown if OK
  1060. * @see list_of_autoecmfiles()
  1061. */
  1062. public function list_of_documents($filearray, $object, $modulepart, $param = '', $forcedownload = 0, $relativepath = '', $permonobject = 1, $useinecm = 0, $textifempty = '', $maxlength = 0, $title = '', $url = '', $showrelpart = 0, $permtoeditline = -1, $upload_dir = '', $sortfield = '', $sortorder = 'ASC', $disablemove = 1, $addfilterfields = 0, $disablecrop = -1)
  1063. {
  1064. // phpcs:enable
  1065. global $user, $conf, $langs, $hookmanager, $form;
  1066. global $sortfield, $sortorder, $maxheightmini;
  1067. global $dolibarr_main_url_root;
  1068. if ($disablecrop == -1) {
  1069. $disablecrop = 1;
  1070. // Values here must be supported by the photo_resize.php page.
  1071. if (in_array($modulepart, array('bank', 'bom', 'expensereport', 'facture', 'facture_fournisseur', 'holiday', 'medias', 'member', 'mrp', 'project', 'product', 'produit', 'propal', 'service', 'societe', 'tax', 'tax-vat', 'ticket', 'user'))) {
  1072. $disablecrop = 0;
  1073. }
  1074. }
  1075. // Define relative path used to store the file
  1076. if (empty($relativepath)) {
  1077. $relativepath = (!empty($object->ref) ?dol_sanitizeFileName($object->ref) : '').'/';
  1078. if (!empty($object->element) && $object->element == 'invoice_supplier') {
  1079. $relativepath = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier').$relativepath; // TODO Call using a defined value for $relativepath
  1080. }
  1081. if (!empty($object->element) && $object->element == 'project_task') {
  1082. $relativepath = 'Call_not_supported_._Call_function_using_a_defined_relative_path_.';
  1083. }
  1084. }
  1085. // For backward compatiblity, we detect file stored into an old path
  1086. if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO) && $filearray[0]['level1name'] == 'photos') {
  1087. $relativepath = preg_replace('/^.*\/produit\//', '', $filearray[0]['path']).'/';
  1088. }
  1089. // Defined relative dir to DOL_DATA_ROOT
  1090. $relativedir = '';
  1091. if ($upload_dir) {
  1092. $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $upload_dir);
  1093. $relativedir = preg_replace('/^[\\/]/', '', $relativedir);
  1094. }
  1095. // For example here $upload_dir = '/pathtodocuments/commande/SO2001-123/'
  1096. // For example here $upload_dir = '/pathtodocuments/tax/vat/1'
  1097. $hookmanager->initHooks(array('formfile'));
  1098. $parameters = array(
  1099. 'filearray' => $filearray,
  1100. 'modulepart'=> $modulepart,
  1101. 'param' => $param,
  1102. 'forcedownload' => $forcedownload,
  1103. 'relativepath' => $relativepath, // relative filename to module dir
  1104. 'relativedir' => $relativedir, // relative dirname to DOL_DATA_ROOT
  1105. 'permtodelete' => $permonobject,
  1106. 'useinecm' => $useinecm,
  1107. 'textifempty' => $textifempty,
  1108. 'maxlength' => $maxlength,
  1109. 'title' => $title,
  1110. 'url' => $url
  1111. );
  1112. $reshook = $hookmanager->executeHooks('showFilesList', $parameters, $object);
  1113. if (!empty($reshook)) { // null or '' for bypass
  1114. return $reshook;
  1115. } else {
  1116. if (!is_object($form)) {
  1117. include_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; // The compoent may be included into ajax page that does not include the Form class
  1118. $form = new Form($this->db);
  1119. }
  1120. if (!preg_match('/&id=/', $param) && isset($object->id)) {
  1121. $param .= '&id='.$object->id;
  1122. }
  1123. $relativepathwihtoutslashend = preg_replace('/\/$/', '', $relativepath);
  1124. if ($relativepathwihtoutslashend) {
  1125. $param .= '&file='.urlencode($relativepathwihtoutslashend);
  1126. }
  1127. if ($permtoeditline < 0) { // Old behaviour for backward compatibility. New feature should call method with value 0 or 1
  1128. $permtoeditline = 0;
  1129. if (in_array($modulepart, array('product', 'produit', 'service'))) {
  1130. if ($user->rights->produit->creer && $object->type == Product::TYPE_PRODUCT) {
  1131. $permtoeditline = 1;
  1132. }
  1133. if ($user->rights->service->creer && $object->type == Product::TYPE_SERVICE) {
  1134. $permtoeditline = 1;
  1135. }
  1136. }
  1137. }
  1138. if (empty($conf->global->MAIN_UPLOAD_DOC)) {
  1139. $permtoeditline = 0;
  1140. $permonobject = 0;
  1141. }
  1142. // Show list of existing files
  1143. if ((empty($useinecm) || $useinecm == 6) && $title != 'none') {
  1144. print load_fiche_titre($title ? $title : $langs->trans("AttachedFiles"), '', 'file-upload', 0, '', 'table-list-of-attached-files');
  1145. }
  1146. if (empty($url)) {
  1147. $url = $_SERVER["PHP_SELF"];
  1148. }
  1149. print '<!-- html.formfile::list_of_documents -->'."\n";
  1150. if (GETPOST('action', 'aZ09') == 'editfile' && $permtoeditline) {
  1151. print '<form action="'.$_SERVER["PHP_SELF"].'?'.$param.'" method="POST">';
  1152. print '<input type="hidden" name="token" value="'.newToken().'">';
  1153. print '<input type="hidden" name="action" value="renamefile">';
  1154. print '<input type="hidden" name="id" value="'.$object->id.'">';
  1155. print '<input type="hidden" name="modulepart" value="'.$modulepart.'">';
  1156. }
  1157. print '<div class="div-table-responsive-no-min">';
  1158. print '<table id="tablelines" class="centpercent liste noborder nobottom">'."\n";
  1159. if (!empty($addfilterfields)) {
  1160. print '<tr class="liste_titre nodrag nodrop">';
  1161. print '<td><input type="search_doc_ref" value="'.dol_escape_htmltag(GETPOST('search_doc_ref', 'alpha')).'"></td>';
  1162. print '<td></td>';
  1163. print '<td></td>';
  1164. if (empty($useinecm) || $useinecm == 4 || $useinecm == 5 || $useinecm == 6) {
  1165. print '<td></td>';
  1166. }
  1167. print '<td></td>';
  1168. print '<td></td>';
  1169. if (empty($disablemove) && count($filearray) > 1) {
  1170. print '<td></td>';
  1171. }
  1172. print "</tr>\n";
  1173. }
  1174. // Get list of files stored into database for same relative directory
  1175. if ($relativedir) {
  1176. completeFileArrayWithDatabaseInfo($filearray, $relativedir);
  1177. //var_dump($sortfield.' - '.$sortorder);
  1178. if ($sortfield && $sortorder) { // If $sortfield is for example 'position_name', we will sort on the property 'position_name' (that is concat of position+name)
  1179. $filearray = dol_sort_array($filearray, $sortfield, $sortorder);
  1180. }
  1181. }
  1182. print '<tr class="liste_titre nodrag nodrop">';
  1183. //print $url.' sortfield='.$sortfield.' sortorder='.$sortorder;
  1184. print_liste_field_titre('Documents2', $url, "name", "", $param, '', $sortfield, $sortorder, 'left ');
  1185. print_liste_field_titre('Size', $url, "size", "", $param, '', $sortfield, $sortorder, 'right ');
  1186. print_liste_field_titre('Date', $url, "date", "", $param, '', $sortfield, $sortorder, 'center ');
  1187. if (empty($useinecm) || $useinecm == 4 || $useinecm == 5 || $useinecm == 6) {
  1188. print_liste_field_titre('', $url, "", "", $param, '', $sortfield, $sortorder, 'center '); // Preview
  1189. }
  1190. // Shared or not - Hash of file
  1191. print_liste_field_titre('');
  1192. // Action button
  1193. print_liste_field_titre('');
  1194. if (empty($disablemove) && count($filearray) > 1) {
  1195. print_liste_field_titre('');
  1196. }
  1197. print "</tr>\n";
  1198. $nboffiles = count($filearray);
  1199. if ($nboffiles > 0) {
  1200. include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
  1201. }
  1202. $i = 0;
  1203. $nboflines = 0;
  1204. $lastrowid = 0;
  1205. foreach ($filearray as $key => $file) { // filearray must be only files here
  1206. if ($file['name'] != '.'
  1207. && $file['name'] != '..'
  1208. && !preg_match('/\.meta$/i', $file['name'])) {
  1209. if ($filearray[$key]['rowid'] > 0) {
  1210. $lastrowid = $filearray[$key]['rowid'];
  1211. }
  1212. $filepath = $relativepath.$file['name'];
  1213. $editline = 0;
  1214. $nboflines++;
  1215. print '<!-- Line list_of_documents '.$key.' relativepath = '.$relativepath.' -->'."\n";
  1216. // Do we have entry into database ?
  1217. print '<!-- In database: position='.$filearray[$key]['position'].' -->'."\n";
  1218. print '<tr class="oddeven" id="row-'.($filearray[$key]['rowid'] > 0 ? $filearray[$key]['rowid'] : 'AFTER'.$lastrowid.'POS'.($i + 1)).'">';
  1219. // File name
  1220. print '<td class="minwith200 tdoverflowmax500">';
  1221. // Show file name with link to download
  1222. //print "XX".$file['name']; //$file['name'] must be utf8
  1223. print '<a class="paddingright valignmiddle" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart;
  1224. if ($forcedownload) {
  1225. print '&attachment=1';
  1226. }
  1227. if (!empty($object->entity)) {
  1228. print '&entity='.$object->entity;
  1229. }
  1230. print '&file='.urlencode($filepath);
  1231. print '">';
  1232. print img_mime($file['name'], $file['name'].' ('.dol_print_size($file['size'], 0, 0).')', 'inline-block valignmiddle paddingright');
  1233. if ($showrelpart == 1) {
  1234. print $relativepath;
  1235. }
  1236. //print dol_trunc($file['name'],$maxlength,'middle');
  1237. if (GETPOST('action', 'aZ09') == 'editfile' && $file['name'] == basename(GETPOST('urlfile', 'alpha'))) {
  1238. print '</a>';
  1239. $section_dir = dirname(GETPOST('urlfile', 'alpha'));
  1240. if (!preg_match('/\/$/', $section_dir)) {
  1241. $section_dir .= '/';
  1242. }
  1243. print '<input type="hidden" name="section_dir" value="'.$section_dir.'">';
  1244. print '<input type="hidden" name="renamefilefrom" value="'.dol_escape_htmltag($file['name']).'">';
  1245. print '<input type="text" name="renamefileto" class="quatrevingtpercent" value="'.dol_escape_htmltag($file['name']).'">';
  1246. $editline = 1;
  1247. } else {
  1248. $filenametoshow = preg_replace('/\.noexe$/', '', $file['name']);
  1249. print dol_escape_htmltag(dol_trunc($filenametoshow, 200));
  1250. print '</a>';
  1251. }
  1252. // Preview link
  1253. if (!$editline) {
  1254. print $this->showPreview($file, $modulepart, $filepath, 0, 'entity='.(!empty($object->entity) ? $object->entity : $conf->entity));
  1255. }
  1256. print "</td>\n";
  1257. // Size
  1258. $sizetoshow = dol_print_size($file['size'], 1, 1);
  1259. $sizetoshowbytes = dol_print_size($file['size'], 0, 1);
  1260. print '<td class="right nowraponall">';
  1261. if ($sizetoshow == $sizetoshowbytes) {
  1262. print $sizetoshow;
  1263. } else {
  1264. print $form->textwithpicto($sizetoshow, $sizetoshowbytes, -1);
  1265. }
  1266. print '</td>';
  1267. // Date
  1268. print '<td class="center nowraponall">'.dol_print_date($file['date'], "dayhour", "tzuser").'</td>';
  1269. // Preview
  1270. if (empty($useinecm) || $useinecm == 4 || $useinecm == 5 || $useinecm == 6) {
  1271. $fileinfo = pathinfo($file['name']);
  1272. print '<td class="center">';
  1273. if (image_format_supported($file['name']) >= 0) {
  1274. if ($useinecm == 5 || $useinecm == 6) {
  1275. $smallfile = getImageFileNameForSize($file['name'], ''); // There is no thumb for ECM module and Media filemanager, so we use true image. TODO Change this it is slow on image dir.
  1276. } else {
  1277. $smallfile = getImageFileNameForSize($file['name'], '_small'); // For new thumbs using same ext (in lower case however) than original
  1278. }
  1279. if (!dol_is_file($file['path'].'/'.$smallfile)) {
  1280. $smallfile = getImageFileNameForSize($file['name'], '_small', '.png'); // For backward compatibility of old thumbs that were created with filename in lower case and with .png extension
  1281. }
  1282. //print $file['path'].'/'.$smallfile.'<br>';
  1283. $urlforhref = getAdvancedPreviewUrl($modulepart, $relativepath.$fileinfo['filename'].'.'.strtolower($fileinfo['extension']), 1, '&entity='.(!empty($object->entity) ? $object->entity : $conf->entity));
  1284. if (empty($urlforhref)) {
  1285. $urlforhref = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.(!empty($object->entity) ? $object->entity : $conf->entity).'&file='.urlencode($relativepath.$fileinfo['filename'].'.'.strtolower($fileinfo['extension']));
  1286. print '<a href="'.$urlforhref.'" class="aphoto" target="_blank" rel="noopener noreferrer">';
  1287. } else {
  1288. print '<a href="'.$urlforhref['url'].'" class="'.$urlforhref['css'].'" target="'.$urlforhref['target'].'" mime="'.$urlforhref['mime'].'">';
  1289. }
  1290. print '<img class="photo maxwidth200 shadow valignmiddle" height="'.(($useinecm == 4 || $useinecm == 5 || $useinecm == 6) ? '20' : $maxheightmini).'" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.(!empty($object->entity) ? $object->entity : $conf->entity).'&file='.urlencode($relativepath.$smallfile).'" title="">';
  1291. print '</a>';
  1292. } else {
  1293. print '&nbsp;';
  1294. }
  1295. print '</td>';
  1296. }
  1297. // Shared or not - Hash of file
  1298. print '<td class="center">';
  1299. if ($relativedir && $filearray[$key]['rowid'] > 0) { // only if we are in a mode where a scan of dir were done and we have id of file in ECM table
  1300. if ($editline) {
  1301. print '<label for="idshareenabled'.$key.'">'.$langs->trans("FileSharedViaALink").'</label> ';
  1302. print '<input class="inline-block" type="checkbox" id="idshareenabled'.$key.'" name="shareenabled"'.($file['share'] ? ' checked="checked"' : '').' /> ';
  1303. } else {
  1304. if ($file['share']) {
  1305. // Define $urlwithroot
  1306. $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
  1307. $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
  1308. //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
  1309. //print '<span class="opacitymedium">'.$langs->trans("Hash").' : '.$file['share'].'</span>';
  1310. $forcedownload = 0;
  1311. $paramlink = '';
  1312. if (!empty($file['share'])) {
  1313. $paramlink .= ($paramlink ? '&' : '').'hashp='.$file['share']; // Hash for public share
  1314. }
  1315. if ($forcedownload) {
  1316. $paramlink .= ($paramlink ? '&' : '').'attachment=1';
  1317. }
  1318. $fulllink = $urlwithroot.'/document.php'.($paramlink ? '?'.$paramlink : '');
  1319. print img_picto($langs->trans("FileSharedViaALink"), 'globe').' ';
  1320. print '<input type="text" class="quatrevingtpercent minwidth200imp nopadding small" id="downloadlink'.$filearray[$key]['rowid'].'" name="downloadexternallink" title="'.dol_escape_htmltag($langs->trans("FileSharedViaALink")).'" value="'.dol_escape_htmltag($fulllink).'">';
  1321. } else {
  1322. //print '<span class="opacitymedium">'.$langs->trans("FileNotShared").'</span>';
  1323. }
  1324. }
  1325. }
  1326. print '</td>';
  1327. // Actions buttons (1 column or 2 if !disablemove)
  1328. if (!$editline) {
  1329. // Delete or view link
  1330. // ($param must start with &)
  1331. print '<td class="valignmiddle right actionbuttons nowraponall"><!-- action on files -->';
  1332. if ($useinecm == 1 || $useinecm == 5) { // ECM manual tree only
  1333. // $section is inside $param
  1334. $newparam .= preg_replace('/&file=.*$/', '', $param); // We don't need param file=
  1335. $backtopage = DOL_URL_ROOT.'/ecm/index.php?&section_dir='.urlencode($relativepath).$newparam;
  1336. print '<a class="editfielda editfilelink" href="'.DOL_URL_ROOT.'/ecm/file_card.php?urlfile='.urlencode($file['name']).$param.'&backtopage='.urlencode($backtopage).'" rel="'.urlencode($file['name']).'">'.img_edit('default', 0, 'class="paddingrightonly"').'</a>';
  1337. }
  1338. if (empty($useinecm) || $useinecm == 2 || $useinecm == 6) { // 6=Media file manager
  1339. $newmodulepart = $modulepart;
  1340. if (in_array($modulepart, array('product', 'produit', 'service'))) {
  1341. $newmodulepart = 'produit|service';
  1342. }
  1343. if (!$disablecrop && image_format_supported($file['name']) > 0) {
  1344. if ($permtoeditline) {
  1345. // Link to resize
  1346. $moreparaminurl = '';
  1347. if ($object->id > 0) {
  1348. $moreparaminurl = '&id='.$object->id;
  1349. } elseif (GETPOST('website', 'alpha')) {
  1350. $moreparaminurl = '&website='.GETPOST('website', 'alpha');
  1351. }
  1352. print '<a class="editfielda" href="'.DOL_URL_ROOT.'/core/photos_resize.php?modulepart='.urlencode($newmodulepart).$moreparaminurl.'&file='.urlencode($relativepath.$fileinfo['filename'].'.'.strtolower($fileinfo['extension'])).'" title="'.dol_escape_htmltag($langs->trans("ResizeOrCrop")).'">'.img_picto($langs->trans("ResizeOrCrop"), 'resize', 'class="paddingrightonly"').'</a>';
  1353. }
  1354. }
  1355. if ($permtoeditline) {
  1356. $paramsectiondir = (in_array($modulepart, array('medias', 'ecm')) ? '&section_dir='.urlencode($relativepath) : '');
  1357. print '<a class="editfielda reposition editfilelink" href="'.(($useinecm == 1 || $useinecm == 5) ? '#' : ($url.'?action=editfile&token='.newToken().'&urlfile='.urlencode($filepath).$paramsectiondir.$param)).'" rel="'.$filepath.'">'.img_edit('default', 0, 'class="paddingrightonly"').'</a>';
  1358. }
  1359. }
  1360. if ($permonobject) {
  1361. $useajax = 1;
  1362. if (!empty($conf->dol_use_jmobile)) {
  1363. $useajax = 0;
  1364. }
  1365. if (empty($conf->use_javascript_ajax)) {
  1366. $useajax = 0;
  1367. }
  1368. if (!empty($conf->global->MAIN_ECM_DISABLE_JS)) {
  1369. $useajax = 0;
  1370. }
  1371. print '<a href="'.((($useinecm && $useinecm != 6) && $useajax) ? '#' : ($url.'?action=deletefile&token='.newToken().'&urlfile='.urlencode($filepath).$param)).'" class="reposition deletefilelink" rel="'.$filepath.'">'.img_delete().'</a>';
  1372. }
  1373. print "</td>";
  1374. if (empty($disablemove) && count($filearray) > 1) {
  1375. if ($nboffiles > 1 && $conf->browser->layout != 'phone') {
  1376. print '<td class="linecolmove tdlineupdown center">';
  1377. if ($i > 0) {
  1378. print '<a class="lineupdown" href="'.$_SERVER["PHP_SELF"].'?id='.$this->id.'&action=up&rowid='.$line->id.'">'.img_up('default', 0, 'imgupforline').'</a>';
  1379. }
  1380. if ($i < ($nboffiles - 1)) {
  1381. print '<a class="lineupdown" href="'.$_SERVER["PHP_SELF"].'?id='.$this->id.'&action=down&rowid='.$line->id.'">'.img_down('default', 0, 'imgdownforline').'</a>';
  1382. }
  1383. print '</td>';
  1384. } else {
  1385. print '<td'.(($conf->browser->layout != 'phone') ? ' class="linecolmove tdlineupdown center"' : ' class="linecolmove center"').'>';
  1386. print '</td>';
  1387. }
  1388. }
  1389. } else {
  1390. print '<td class="right">';
  1391. print '<input type="hidden" name="ecmfileid" value="'.$filearray[$key]['rowid'].'">';
  1392. print '<input type="submit" class="button button-save" name="renamefilesave" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  1393. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  1394. print '</td>';
  1395. if (empty($disablemove) && count($filearray) > 1) {
  1396. print '<td class="right"></td>';
  1397. }
  1398. }
  1399. print "</tr>\n";
  1400. $i++;
  1401. }
  1402. }
  1403. if ($nboffiles == 0) {
  1404. $colspan = '6';
  1405. if (empty($disablemove) && count($filearray) > 1) {
  1406. $colspan++; // 6 columns or 7
  1407. }
  1408. print '<tr class="oddeven"><td colspan="'.$colspan.'">';
  1409. if (empty($textifempty)) {
  1410. print '<span class="opacitymedium">'.$langs->trans("NoFileFound").'</span>';
  1411. } else {
  1412. print '<span class="opacitymedium">'.$textifempty.'</span>';
  1413. }
  1414. print '</td></tr>';
  1415. }
  1416. print "</table>";
  1417. print '</div>';
  1418. if ($nboflines > 1 && is_object($object)) {
  1419. if (!empty($conf->use_javascript_ajax) && $permtoeditline) {
  1420. $table_element_line = 'ecm_files';
  1421. include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
  1422. }
  1423. }
  1424. print ajax_autoselect('downloadlink');
  1425. if (GETPOST('action', 'aZ09') == 'editfile' && $permtoeditline) {
  1426. print '</form>';
  1427. }
  1428. return $nboffiles;
  1429. }
  1430. }
  1431. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  1432. /**
  1433. * Show list of documents in a directory of ECM module.
  1434. *
  1435. * @param string $upload_dir Directory that was scanned. This directory will contains files into subdirs REF/files
  1436. * @param array $filearray Array of files loaded by dol_dir_list function before calling this function
  1437. * @param string $modulepart Value for modulepart used by download wrapper. Value can be $object->table_name (that is 'myobject' or 'mymodule_myobject') or $object->element.'-'.$module (for compatibility purpose)
  1438. * @param string $param Parameters on sort links
  1439. * @param int $forcedownload Force to open dialog box "Save As" when clicking on file
  1440. * @param string $relativepath Relative path of docs (autodefined if not provided)
  1441. * @param int $permissiontodelete Permission to delete
  1442. * @param int $useinecm Change output for use in ecm module
  1443. * @param int $textifempty Text to show if filearray is empty
  1444. * @param int $maxlength Maximum length of file name shown
  1445. * @param string $url Full url to use for click links ('' = autodetect)
  1446. * @param int $addfilterfields Add line with filters
  1447. * @return int <0 if KO, nb of files shown if OK
  1448. * @see list_of_documents()
  1449. */
  1450. public function list_of_autoecmfiles($upload_dir, $filearray, $modulepart, $param, $forcedownload = 0, $relativepath = '', $permissiontodelete = 1, $useinecm = 0, $textifempty = '', $maxlength = 0, $url = '', $addfilterfields = 0)
  1451. {
  1452. // phpcs:enable
  1453. global $user, $conf, $langs, $hookmanager, $form;
  1454. global $sortfield, $sortorder;
  1455. global $search_doc_ref;
  1456. global $dolibarr_main_url_root;
  1457. dol_syslog(get_class($this).'::list_of_autoecmfiles upload_dir='.$upload_dir.' modulepart='.$modulepart);
  1458. // Show list of documents
  1459. if (empty($useinecm) || $useinecm == 6) {
  1460. print load_fiche_titre($langs->trans("AttachedFiles"));
  1461. }
  1462. if (empty($url)) {
  1463. $url = $_SERVER["PHP_SELF"];
  1464. }
  1465. if (!empty($addfilterfields)) {
  1466. print '<form action="'.$_SERVER['PHP_SELF'].'">';
  1467. print '<input type="hidden" name="token" value="'.newToken().'">';
  1468. print '<input type="hidden" name="module" value="'.$modulepart.'">';
  1469. }
  1470. print '<div class="div-table-responsive-no-min">';
  1471. print '<table width="100%" class="noborder">'."\n";
  1472. if (!empty($addfilterfields)) {
  1473. print '<tr class="liste_titre nodrag nodrop">';
  1474. print '<td class="liste_titre"></td>';
  1475. print '<td class="liste_titre"><input type="text" class="maxwidth100onsmartphone" name="search_doc_ref" value="'.dol_escape_htmltag($search_doc_ref).'"></td>';
  1476. print '<td class="liste_titre"></td>';
  1477. print '<td class="liste_titre"></td>';
  1478. // Action column
  1479. print '<td class="liste_titre right">';
  1480. $searchpicto = $form->showFilterButtons();
  1481. print $searchpicto;
  1482. print '</td>';
  1483. print "</tr>\n";
  1484. }
  1485. print '<tr class="liste_titre">';
  1486. $sortref = "fullname";
  1487. if ($modulepart == 'invoice_supplier') {
  1488. $sortref = 'level1name';
  1489. }
  1490. print_liste_field_titre("Ref", $url, $sortref, "", $param, '', $sortfield, $sortorder);
  1491. print_liste_field_titre("Documents2", $url, "name", "", $param, '', $sortfield, $sortorder);
  1492. print_liste_field_titre("Size", $url, "size", "", $param, '', $sortfield, $sortorder, 'right ');
  1493. print_liste_field_titre("Date", $url, "date", "", $param, '', $sortfield, $sortorder, 'center ');
  1494. print_liste_field_titre("Shared", $url, 'share', '', $param, '', $sortfield, $sortorder, 'right ');
  1495. print '</tr>'."\n";
  1496. // To show ref or specific information according to view to show (defined by $module)
  1497. $object_instance = null;
  1498. if ($modulepart == 'company') {
  1499. include_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
  1500. $object_instance = new Societe($this->db);
  1501. } elseif ($modulepart == 'invoice') {
  1502. include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
  1503. $object_instance = new Facture($this->db);
  1504. } elseif ($modulepart == 'invoice_supplier') {
  1505. include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
  1506. $object_instance = new FactureFournisseur($this->db);
  1507. } elseif ($modulepart == 'propal') {
  1508. include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
  1509. $object_instance = new Propal($this->db);
  1510. } elseif ($modulepart == 'supplier_proposal') {
  1511. include_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
  1512. $object_instance = new SupplierProposal($this->db);
  1513. } elseif ($modulepart == 'order') {
  1514. include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
  1515. $object_instance = new Commande($this->db);
  1516. } elseif ($modulepart == 'order_supplier') {
  1517. include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
  1518. $object_instance = new CommandeFournisseur($this->db);
  1519. } elseif ($modulepart == 'contract') {
  1520. include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
  1521. $object_instance = new Contrat($this->db);
  1522. } elseif ($modulepart == 'product') {
  1523. include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
  1524. $object_instance = new Product($this->db);
  1525. } elseif ($modulepart == 'tax') {
  1526. include_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php';
  1527. $object_instance = new ChargeSociales($this->db);
  1528. } elseif ($modulepart == 'tax-vat') {
  1529. include_once DOL_DOCUMENT_ROOT.'/compta/tva/class/tva.class.php';
  1530. $object_instance = new Tva($this->db);
  1531. } elseif ($modulepart == 'salaries') {
  1532. include_once DOL_DOCUMENT_ROOT.'/salaries/class/salary.class.php';
  1533. $object_instance = new Salary($this->db);
  1534. } elseif ($modulepart == 'project') {
  1535. include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
  1536. $object_instance = new Project($this->db);
  1537. } elseif ($modulepart == 'project_task') {
  1538. include_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
  1539. $object_instance = new Task($this->db);
  1540. } elseif ($modulepart == 'fichinter') {
  1541. include_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
  1542. $object_instance = new Fichinter($this->db);
  1543. } elseif ($modulepart == 'user') {
  1544. include_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
  1545. $object_instance = new User($this->db);
  1546. } elseif ($modulepart == 'expensereport') {
  1547. include_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
  1548. $object_instance = new ExpenseReport($this->db);
  1549. } elseif ($modulepart == 'holiday') {
  1550. include_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
  1551. $object_instance = new Holiday($this->db);
  1552. } elseif ($modulepart == 'recruitment-recruitmentcandidature') {
  1553. include_once DOL_DOCUMENT_ROOT.'/recruitment/class/recruitmentcandidature.class.php';
  1554. $object_instance = new RecruitmentCandidature($this->db);
  1555. } elseif ($modulepart == 'banque') {
  1556. include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
  1557. $object_instance = new Account($this->db);
  1558. } elseif ($modulepart == 'chequereceipt') {
  1559. include_once DOL_DOCUMENT_ROOT.'/compta/paiement/cheque/class/remisecheque.class.php';
  1560. $object_instance = new RemiseCheque($this->db);
  1561. } elseif ($modulepart == 'mrp-mo') {
  1562. include_once DOL_DOCUMENT_ROOT.'/mrp/class/mo.class.php';
  1563. $object_instance = new Mo($this->db);
  1564. } else {
  1565. $parameters = array('modulepart'=>$modulepart);
  1566. $reshook = $hookmanager->executeHooks('addSectionECMAuto', $parameters);
  1567. if ($reshook > 0 && is_array($hookmanager->resArray) && count($hookmanager->resArray) > 0) {
  1568. if (array_key_exists('classpath', $hookmanager->resArray) && !empty($hookmanager->resArray['classpath'])) {
  1569. dol_include_once($hookmanager->resArray['classpath']);
  1570. if (array_key_exists('classname', $hookmanager->resArray) && !empty($hookmanager->resArray['classname'])) {
  1571. if (class_exists($hookmanager->resArray['classname'])) {
  1572. $tmpclassname = $hookmanager->resArray['classname'];
  1573. $object_instance = new $tmpclassname($this->db);
  1574. }
  1575. }
  1576. }
  1577. }
  1578. }
  1579. //var_dump($filearray);
  1580. //var_dump($object_instance);
  1581. // Get list of files stored into database for same relative directory
  1582. $relativepathfromroot = preg_replace('/'.preg_quote(DOL_DATA_ROOT.'/', '/').'/', '', $upload_dir);
  1583. if ($relativepathfromroot) {
  1584. completeFileArrayWithDatabaseInfo($filearray, $relativepathfromroot.'/%');
  1585. //var_dump($sortfield.' - '.$sortorder);
  1586. if ($sortfield && $sortorder) { // If $sortfield is for example 'position_name', we will sort on the property 'position_name' (that is concat of position+name)
  1587. $filearray = dol_sort_array($filearray, $sortfield, $sortorder, 1);
  1588. }
  1589. }
  1590. //var_dump($filearray);
  1591. foreach ($filearray as $key => $file) {
  1592. if (!is_dir($file['name'])
  1593. && $file['name'] != '.'
  1594. && $file['name'] != '..'
  1595. && $file['name'] != 'CVS'
  1596. && !preg_match('/\.meta$/i', $file['name'])) {
  1597. // Define relative path used to store the file
  1598. $relativefile = preg_replace('/'.preg_quote($upload_dir.'/', '/').'/', '', $file['fullname']);
  1599. $id = 0;
  1600. $ref = '';
  1601. // To show ref or specific information according to view to show (defined by $modulepart)
  1602. // $modulepart can be $object->table_name (that is 'mymodule_myobject') or $object->element.'-'.$module (for compatibility purpose)
  1603. $reg = array();
  1604. if ($modulepart == 'company' || $modulepart == 'tax' || $modulepart == 'tax-vat' || $modulepart == 'salaries') {
  1605. preg_match('/(\d+)\/[^\/]+$/', $relativefile, $reg);
  1606. $id = (isset($reg[1]) ? $reg[1] : '');
  1607. } elseif ($modulepart == 'invoice_supplier') {
  1608. preg_match('/([^\/]+)\/[^\/]+$/', $relativefile, $reg);
  1609. $ref = (isset($reg[1]) ? $reg[1] : '');
  1610. if (is_numeric($ref)) {
  1611. $id = $ref;
  1612. $ref = '';
  1613. }
  1614. } elseif ($modulepart == 'user') {
  1615. // $ref may be also id with old supplier invoices
  1616. preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg);
  1617. $id = (isset($reg[1]) ? $reg[1] : '');
  1618. } elseif ($modulepart == 'project_task') {
  1619. // $ref of task is the sub-directory of the project
  1620. $reg = explode("/", $relativefile);
  1621. $ref = (isset($reg[1]) ? $reg[1] : '');
  1622. } elseif (in_array($modulepart, array(
  1623. 'invoice',
  1624. 'propal',
  1625. 'supplier_proposal',
  1626. 'order',
  1627. 'order_supplier',
  1628. 'contract',
  1629. 'product',
  1630. 'project',
  1631. 'project_task',
  1632. 'fichinter',
  1633. 'expensereport',
  1634. 'recruitment-recruitmentcandidature',
  1635. 'mrp-mo',
  1636. 'banque',
  1637. 'chequereceipt',
  1638. 'holiday'))) {
  1639. preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg);
  1640. $ref = (isset($reg[1]) ? $reg[1] : '');
  1641. } else {
  1642. $parameters = array('modulepart'=>$modulepart, 'fileinfo'=>$file);
  1643. $reshook = $hookmanager->executeHooks('addSectionECMAuto', $parameters);
  1644. if ($reshook > 0 && is_array($hookmanager->resArray) && count($hookmanager->resArray) > 0) {
  1645. if (array_key_exists('ref', $hookmanager->resArray) && !empty($hookmanager->resArray['ref'])) {
  1646. $ref = $hookmanager->resArray['ref'];
  1647. }
  1648. if (array_key_exists('id', $hookmanager->resArray) && !empty($hookmanager->resArray['id'])) {
  1649. $id = $hookmanager->resArray['id'];
  1650. }
  1651. }
  1652. //print 'Error: Value for modulepart = '.$modulepart.' is not yet implemented in function list_of_autoecmfiles'."\n";
  1653. }
  1654. if (!$id && !$ref) {
  1655. continue;
  1656. }
  1657. $found = 0;
  1658. if (!empty($this->cache_objects[$modulepart.'_'.$id.'_'.$ref])) {
  1659. $found = 1;
  1660. } else {
  1661. //print 'Fetch '.$id." - ".$ref.' class='.get_class($object_instance).'<br>';
  1662. $result = 0;
  1663. if (is_object($object_instance)) {
  1664. if ($id) {
  1665. $result = $object_instance->fetch($id);
  1666. } else {
  1667. if (!($result = $object_instance->fetch('', $ref))) {
  1668. //fetchOneLike looks for objects with wildcards in its reference.
  1669. //It is useful for those masks who get underscores instead of their actual symbols (because the _ had replaced a forbiddn char)
  1670. //fetchOneLike requires some info in the object. If it doesn't have it, then 0 is returned
  1671. //that's why we look only into fetchOneLike when fetch returns 0
  1672. // TODO Remove this part ?
  1673. $result = $object_instance->fetchOneLike($ref);
  1674. }
  1675. }
  1676. }
  1677. if ($result > 0) { // Save object loaded into a cache
  1678. $found = 1;
  1679. $this->cache_objects[$modulepart.'_'.$id.'_'.$ref] = clone $object_instance;
  1680. }
  1681. if ($result == 0) {
  1682. $found = 1;
  1683. $this->cache_objects[$modulepart.'_'.$id.'_'.$ref] = 'notfound';
  1684. unset($filearray[$key]);
  1685. }
  1686. }
  1687. if (!$found > 0 || !is_object($this->cache_objects[$modulepart.'_'.$id.'_'.$ref])) {
  1688. continue; // We do not show orphelins files
  1689. }
  1690. print '<!-- Line list_of_autoecmfiles key='.$key.' -->'."\n";
  1691. print '<tr class="oddeven">';
  1692. print '<td>';
  1693. if ($found > 0 && is_object($this->cache_objects[$modulepart.'_'.$id.'_'.$ref])) {
  1694. $tmpobject = $this->cache_objects[$modulepart.'_'.$id.'_'.$ref];
  1695. //if (! in_array($tmpobject->element, array('expensereport'))) {
  1696. print $tmpobject->getNomUrl(1, 'document');
  1697. //} else {
  1698. // print $tmpobject->getNomUrl(1);
  1699. //}
  1700. } else {
  1701. print $langs->trans("ObjectDeleted", ($id ? $id : $ref));
  1702. }
  1703. //$modulesubdir=dol_sanitizeFileName($ref);
  1704. //$modulesubdir = dirname($relativefile);
  1705. //$filedir=$conf->$modulepart->dir_output . '/' . dol_sanitizeFileName($obj->ref);
  1706. //$filedir = $file['path'];
  1707. //$urlsource=$_SERVER['PHP_SELF'].'?id='.$obj->rowid;
  1708. //print $formfile->getDocumentsLink($modulepart, $filename, $filedir);
  1709. print '</td>';
  1710. // File
  1711. // Check if document source has external module part, if it the case use it for module part on document.php
  1712. print '<td>';
  1713. //print "XX".$file['name']; //$file['name'] must be utf8
  1714. print '<a href="'.DOL_URL_ROOT.'/document.php?modulepart='.urlencode($modulepart);
  1715. if ($forcedownload) {
  1716. print '&attachment=1';
  1717. }
  1718. print '&file='.urlencode($relativefile).'">';
  1719. print img_mime($file['name'], $file['name'].' ('.dol_print_size($file['size'], 0, 0).')');
  1720. print dol_trunc($file['name'], $maxlength, 'middle');
  1721. print '</a>';
  1722. //print $this->getDocumentsLink($modulepart, $modulesubdir, $filedir, '^'.preg_quote($file['name'],'/').'$');
  1723. print $this->showPreview($file, $modulepart, $file['relativename']);
  1724. print "</td>\n";
  1725. // Size
  1726. $sizetoshow = dol_print_size($file['size'], 1, 1);
  1727. $sizetoshowbytes = dol_print_size($file['size'], 0, 1);
  1728. print '<td class="right nowraponall">';
  1729. if ($sizetoshow == $sizetoshowbytes) {
  1730. print $sizetoshow;
  1731. } else {
  1732. print $form->textwithpicto($sizetoshow, $sizetoshowbytes, -1);
  1733. }
  1734. print '</td>';
  1735. // Date
  1736. print '<td class="center">'.dol_print_date($file['date'], "dayhour").'</td>';
  1737. // Share link
  1738. print '<td class="right">';
  1739. if (!empty($file['share'])) {
  1740. // Define $urlwithroot
  1741. $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
  1742. $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
  1743. //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
  1744. //print '<span class="opacitymedium">'.$langs->trans("Hash").' : '.$file['share'].'</span>';
  1745. $forcedownload = 0;
  1746. $paramlink = '';
  1747. if (!empty($file['share'])) {
  1748. $paramlink .= ($paramlink ? '&' : '').'hashp='.$file['share']; // Hash for public share
  1749. }
  1750. if ($forcedownload) {
  1751. $paramlink .= ($paramlink ? '&' : '').'attachment=1';
  1752. }
  1753. $fulllink = $urlwithroot.'/document.php'.($paramlink ? '?'.$paramlink : '');
  1754. print img_picto($langs->trans("FileSharedViaALink"), 'globe').' ';
  1755. print '<input type="text" class="quatrevingtpercent width100 nopadding nopadding small" id="downloadlink" name="downloadexternallink" value="'.dol_escape_htmltag($fulllink).'">';
  1756. }
  1757. //if (! empty($useinecm) && $useinecm != 6) print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart;
  1758. //if ($forcedownload) print '&attachment=1';
  1759. //print '&file='.urlencode($relativefile).'">';
  1760. //print img_view().'</a> &nbsp; ';
  1761. //if ($permissiontodelete) print '<a href="'.$url.'?id='.$object->id.'&section='.$_REQUEST["section"].'&action=delete&token='.newToken().'&urlfile='.urlencode($file['name']).'">'.img_delete().'</a>';
  1762. //else print '&nbsp;';
  1763. print "</td>";
  1764. print "</tr>\n";
  1765. }
  1766. }
  1767. if (count($filearray) == 0) {
  1768. print '<tr class="oddeven"><td colspan="5">';
  1769. if (empty($textifempty)) {
  1770. print '<span class="opacitymedium">'.$langs->trans("NoFileFound").'</span>';
  1771. } else {
  1772. print '<span class="opacitymedium">'.$textifempty.'</span>';
  1773. }
  1774. print '</td></tr>';
  1775. }
  1776. print "</table>";
  1777. print '</div>';
  1778. if (!empty($addfilterfields)) {
  1779. print '</form>';
  1780. }
  1781. // Fin de zone
  1782. }
  1783. /**
  1784. * Show form to upload a new file with jquery fileupload.
  1785. * This form use the fileupload.php file.
  1786. *
  1787. * @param Object $object Object to use
  1788. * @return void
  1789. */
  1790. private function _formAjaxFileUpload($object)
  1791. {
  1792. global $langs, $conf;
  1793. // PHP post_max_size
  1794. $post_max_size = ini_get('post_max_size');
  1795. $mul_post_max_size = substr($post_max_size, -1);
  1796. $mul_post_max_size = ($mul_post_max_size == 'M' ? 1048576 : ($mul_post_max_size == 'K' ? 1024 : ($mul_post_max_size == 'G' ? 1073741824 : 1)));
  1797. $post_max_size = $mul_post_max_size * (int) $post_max_size;
  1798. // PHP upload_max_filesize
  1799. $upload_max_filesize = ini_get('upload_max_filesize');
  1800. $mul_upload_max_filesize = substr($upload_max_filesize, -1);
  1801. $mul_upload_max_filesize = ($mul_upload_max_filesize == 'M' ? 1048576 : ($mul_upload_max_filesize == 'K' ? 1024 : ($mul_upload_max_filesize == 'G' ? 1073741824 : 1)));
  1802. $upload_max_filesize = $mul_upload_max_filesize * (int) $upload_max_filesize;
  1803. // Max file size
  1804. $max_file_size = (($post_max_size < $upload_max_filesize) ? $post_max_size : $upload_max_filesize);
  1805. // Include main
  1806. include DOL_DOCUMENT_ROOT.'/core/tpl/ajax/fileupload_main.tpl.php';
  1807. // Include template
  1808. include DOL_DOCUMENT_ROOT.'/core/tpl/ajax/fileupload_view.tpl.php';
  1809. }
  1810. /**
  1811. * Show array with linked files
  1812. *
  1813. * @param Object $object Object
  1814. * @param int $permissiontodelete Deletion is allowed
  1815. * @param string $action Action
  1816. * @param string $selected ???
  1817. * @param string $param More param to add into URL
  1818. * @return int Number of links
  1819. */
  1820. public function listOfLinks($object, $permissiontodelete = 1, $action = null, $selected = null, $param = '')
  1821. {
  1822. global $user, $conf, $langs, $user;
  1823. global $sortfield, $sortorder;
  1824. $langs->load("link");
  1825. require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
  1826. $link = new Link($this->db);
  1827. $links = array();
  1828. if ($sortfield == "name") {
  1829. $sortfield = "label";
  1830. } elseif ($sortfield == "date") {
  1831. $sortfield = "datea";
  1832. } else {
  1833. $sortfield = null;
  1834. }
  1835. $res = $link->fetchAll($links, $object->element, $object->id, $sortfield, $sortorder);
  1836. $param .= (isset($object->id) ? '&id='.$object->id : '');
  1837. print '<!-- listOfLinks -->'."\n";
  1838. // Show list of associated links
  1839. print load_fiche_titre($langs->trans("LinkedFiles"), '', 'link', 0, '', 'table-list-of-links');
  1840. print '<form action="'.$_SERVER['PHP_SELF'].($param ? '?'.$param : '').'" method="POST">';
  1841. print '<input type="hidden" name="token" value="'.newToken().'">';
  1842. print '<table class="liste noborder nobottom centpercent">';
  1843. print '<tr class="liste_titre">';
  1844. print_liste_field_titre(
  1845. $langs->trans("Links"),
  1846. $_SERVER['PHP_SELF'],
  1847. "name",
  1848. "",
  1849. $param,
  1850. '',
  1851. $sortfield,
  1852. $sortorder,
  1853. ''
  1854. );
  1855. print_liste_field_titre(
  1856. "",
  1857. "",
  1858. "",
  1859. "",
  1860. "",
  1861. '',
  1862. '',
  1863. '',
  1864. 'right '
  1865. );
  1866. print_liste_field_titre(
  1867. $langs->trans("Date"),
  1868. $_SERVER['PHP_SELF'],
  1869. "date",
  1870. "",
  1871. $param,
  1872. '',
  1873. $sortfield,
  1874. $sortorder,
  1875. 'center '
  1876. );
  1877. print_liste_field_titre(
  1878. '',
  1879. $_SERVER['PHP_SELF'],
  1880. "",
  1881. "",
  1882. $param,
  1883. '',
  1884. '',
  1885. '',
  1886. 'center '
  1887. );
  1888. print_liste_field_titre('', '', '');
  1889. print '</tr>';
  1890. $nboflinks = count($links);
  1891. if ($nboflinks > 0) {
  1892. include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
  1893. }
  1894. foreach ($links as $link) {
  1895. print '<tr class="oddeven">';
  1896. //edit mode
  1897. if ($action == 'update' && $selected === $link->id) {
  1898. print '<td>';
  1899. print '<input type="hidden" name="id" value="'.$object->id.'">';
  1900. print '<input type="hidden" name="linkid" value="'.$link->id.'">';
  1901. print '<input type="hidden" name="action" value="confirm_updateline">';
  1902. print $langs->trans('Link').': <input type="text" name="link" value="'.$link->url.'">';
  1903. print '</td>';
  1904. print '<td>';
  1905. print $langs->trans('Label').': <input type="text" name="label" value="'.dol_escape_htmltag($link->label).'">';
  1906. print '</td>';
  1907. print '<td class="center">'.dol_print_date(dol_now(), "dayhour", "tzuser").'</td>';
  1908. print '<td class="right"></td>';
  1909. print '<td class="right">';
  1910. print '<input type="submit" class="button button-save" name="save" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
  1911. print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
  1912. print '</td>';
  1913. } else {
  1914. print '<td>';
  1915. print img_picto('', 'globe').' ';
  1916. print '<a data-ajax="false" href="'.$link->url.'" target="_blank" rel="noopener noreferrer">';
  1917. print dol_escape_htmltag($link->label);
  1918. print '</a>';
  1919. print '</td>'."\n";
  1920. print '<td class="right"></td>';
  1921. print '<td class="center">'.dol_print_date($link->datea, "dayhour", "tzuser").'</td>';
  1922. print '<td class="center"></td>';
  1923. print '<td class="right">';
  1924. print '<a href="'.$_SERVER['PHP_SELF'].'?action=update&linkid='.$link->id.$param.'&token='.newToken().'" class="editfilelink editfielda reposition" >'.img_edit().'</a>'; // id= is included into $param
  1925. if ($permissiontodelete) {
  1926. print ' &nbsp; <a class="deletefilelink reposition" href="'.$_SERVER['PHP_SELF'].'?action=deletelink&token='.newToken().'&linkid='.((int) $link->id).$param.'">'.img_delete().'</a>'; // id= is included into $param
  1927. } else {
  1928. print '&nbsp;';
  1929. }
  1930. print '</td>';
  1931. }
  1932. print "</tr>\n";
  1933. }
  1934. if ($nboflinks == 0) {
  1935. print '<tr class="oddeven"><td colspan="5">';
  1936. print '<span class="opacitymedium">'.$langs->trans("NoLinkFound").'</span>';
  1937. print '</td></tr>';
  1938. }
  1939. print "</table>";
  1940. print '</form>';
  1941. return $nboflinks;
  1942. }
  1943. /**
  1944. * Show detail icon with link for preview
  1945. *
  1946. * @param array $file Array with data of file. Example: array('name'=>...)
  1947. * @param string $modulepart propal, facture, facture_fourn, ...
  1948. * @param string $relativepath Relative path of docs
  1949. * @param integer $ruleforpicto Rule for picto: 0=Use the generic preview picto, 1=Use the picto of mime type of file). Use a negative value to show a generic picto even if preview not available.
  1950. * @param string $param More param on http links
  1951. * @return string $out Output string with HTML
  1952. */
  1953. public function showPreview($file, $modulepart, $relativepath, $ruleforpicto = 0, $param = '')
  1954. {
  1955. global $langs, $conf;
  1956. $out = '';
  1957. if ($conf->browser->layout != 'phone' && !empty($conf->use_javascript_ajax)) {
  1958. $urladvancedpreview = getAdvancedPreviewUrl($modulepart, $relativepath, 1, $param); // Return if a file is qualified for preview.
  1959. if (count($urladvancedpreview)) {
  1960. $out .= '<a class="pictopreview '.$urladvancedpreview['css'].'" href="'.$urladvancedpreview['url'].'"'.(empty($urladvancedpreview['mime']) ? '' : ' mime="'.$urladvancedpreview['mime'].'"').' '.(empty($urladvancedpreview['target']) ? '' : ' target="'.$urladvancedpreview['target'].'"').'>';
  1961. //$out.= '<a class="pictopreview">';
  1962. if (empty($ruleforpicto)) {
  1963. //$out.= img_picto($langs->trans('Preview').' '.$file['name'], 'detail');
  1964. $out .= '<span class="fa fa-search-plus pictofixedwidth" style="color: gray"></span>';
  1965. } else {
  1966. $out .= img_mime($relativepath, $langs->trans('Preview').' '.$file['name'], 'pictofixedwidth');
  1967. }
  1968. $out .= '</a>';
  1969. } else {
  1970. if ($ruleforpicto < 0) {
  1971. $out .= img_picto('', 'generic', '', false, 0, 0, '', 'paddingright pictofixedwidth');
  1972. }
  1973. }
  1974. }
  1975. return $out;
  1976. }
  1977. }