Passed
Pull Request — dev (#8)
by Rafael
58:47
created

FormFile   F

Complexity

Total Complexity 528

Size/Duplication

Total Lines 2160
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 1275
dl 0
loc 2160
rs 0.8
c 0
b 0
f 0
wmc 528

9 Methods

Rating   Name   Duplication   Size   Complexity  
F list_of_documents() 0 466 159
C listOfLinks() 0 130 11
A show_documents() 0 6 1
F list_of_autoecmfiles() 0 355 92
F form_attach_new_file() 0 189 47
D getDocumentsLink() 0 106 24
B showPreview() 0 24 8
A __construct() 0 4 1
F showdocuments() 0 677 185

How to fix   Complexity   

Complex Class

Complex classes like FormFile often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FormFile, and based on these observations, apply Extract Interface, too.

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