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

FormFile::showdocuments()   F

Complexity

Conditions 185
Paths > 20000

Size

Total Lines 677
Code Lines 427

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 185
eloc 427
nc 29290218
nop 21
dl 0
loc 677
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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