dolibarr 23.0.3
ecmfiles.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2014-2016 Juanjo Menent <jmenent@2byte.es>
4 * Copyright (C) 2015 Florian Henry <florian.henry@open-concept.pro>
5 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
6 * Copyright (C) 2018 Francis Appels <francis.appels@yahoo.com>
7 * Copyright (C) 2019-2025 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
30// Put here all includes required by your class file
31require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
32require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
33
38{
42 public $element = 'ecmfiles';
43
47 public $table_element = 'ecm_files';
48
52 public $picto = 'folder-open';
53
58 public $label;
59
63 public $share;
64
68 public $filename;
69
73 public $filepath;
74
78 public $fullpath_orig;
79
83 public $description;
84
88 public $keywords;
89
93 public $content;
94
98 public $cover;
99
103 public $position;
104
108 public $gen_or_uploaded;
109
113 public $extraparams;
114
118 public $date_c = '';
119
123 public $date_m = '';
124
128 public $fk_user_c;
129
133 public $fk_user_m;
134
138 public $acl;
139
143 public $src_object_type;
144
148 public $src_object_id;
149
153 public $agenda_id;
154
158 public $section_id;
159
160 public $fields = array(
161 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
162 'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'position' => 20, 'notnull' => 1, 'visible' => -1, 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'validate' => 1, 'comment' => "contains hash from filename+filepath"),
163 'label' => array('type' => 'varchar(128)', 'label' => 'Label', 'enabled' => 1, 'position' => 30, 'notnull' => 0, 'visible' => -1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1, 'comment' => "contains hash of file content"),
164 'share' => array('type' => 'varchar(128)', 'label' => 'Share', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => -1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1, 'comment' => "contains hash for file sharing"),
165 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 50, 'index' => 1),
166 'filepath' => array('type' => 'varchar(255)', 'label' => 'FilePath', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => 0, 'searchall' => 0, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1,'comment' => "relative to dolibarr document dir. Example module/def"),
167 'filename' => array('type' => 'varchar(255)', 'label' => 'FileName', 'enabled' => 1, 'position' => 70, 'notnull' => 0, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1,'comment' => "file name only without any directory"),
168 'src_object_type' => array('type' => 'varchar(64)', 'label' => 'SourceType', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'visible' => 0, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1,'comment' => "Source object type ('proposal', 'invoice', ...)"),
169 'src_object_id' => array('type' => 'integer', 'label' => 'SourceID', 'default' => '1', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 90, 'index' => 1, 'comment' => "Source object id"),
170 'fullpath_orig' => array('type' => 'varchar(750)', 'label' => 'FullPathOrig', 'enabled' => 1, 'position' => 100, 'notnull' => 0, 'visible' => 0, 'searchall' => 0, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1,'comment' => "full path of original filename, when file is uploaded from a local computer"),
171 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'visible' => 0, 'position' => 110),
172 'keywords' => array('type' => 'varchar(750)', 'label' => 'Keywords', 'enabled' => 1, 'position' => 120, 'notnull' => 0, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1,'comment' => "list of keywords, separated with comma. Must be limited to most important keywords."),
173 'content' => array('type' => 'html', 'label' => 'Content', 'enabled' => 'getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")', 'position' => 120, 'notnull' => 0, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'csslist' => 'tdoverflowmax200', 'help' => "Text content of file", 'showoncombobox' => 2, 'validate' => 1,'comment' => "Text content if option to store txt content was set."),
174 'cover' => array('type' => 'text', 'label' => 'Cover', 'enabled' => 1, 'visible' => 0, 'position' => 130, 'comment' => "is this file a file to use for a cover"),
175 'position' => array('type' => 'integer', 'label' => 'Position', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 140, 'index' => 1, 'comment' => "position of file among others"),
176 'gen_or_uploaded' => array('type' => 'varchar(12)', 'label' => 'GenOrUpload', 'enabled' => 1, 'position' => 150, 'notnull' => 0, 'visible' => -1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1,'comment' => "'generated' or 'uploaded'"),
177 'extraparams' => array('type' => 'varchar(255)', 'label' => 'ExtraParams', 'enabled' => 1, 'position' => 160, 'notnull' => 0, 'visible' => 1, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'showoncombobox' => 2, 'validate' => 1, 'comment' => "for stocking other parameters with json format"),
178 'date_c' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 170),
179 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 175),
180 'fk_user_c' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'position' => 510, 'notnull' => 1, 'visible' => -2, 'foreignkey' => 'user.rowid',),
181 'fk_user_m' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
182 'note_public' => array('type' => 'text', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 155),
183 'note_private' => array('type' => 'text', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 160),
184 'acl' => array('type' => 'text', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 160, 'comment' => "for future permission 'per file'"),
185 'agenda_id' => array('type' => 'integer', 'label' => 'IdAgenda', 'enabled' => 1, 'visible' => 0, 'position' => 180, 'comment' => "Link to an actioncomm"),
186 );
187
188
194 public function __construct(DoliDB $db)
195 {
196 $this->db = $db;
197 }
198
206 public function create(User $user, $notrigger = 0)
207 {
208 global $conf;
209
210 dol_syslog(__METHOD__, LOG_DEBUG);
211
212 $error = 0;
213
214 // Clean parameters
215 if (isset($this->ref)) {
216 $this->ref = trim($this->ref);
217 }
218 if (isset($this->label)) {
219 $this->label = trim($this->label);
220 }
221 if (isset($this->share)) {
222 $this->share = trim($this->share);
223 }
224 if (isset($this->entity)) {
225 $this->entity = (int) $this->entity;
226 }
227 if (isset($this->filename)) {
228 $this->filename = preg_replace('/\.noexe$/', '', trim($this->filename));
229 }
230 if (isset($this->filepath)) {
231 $this->filepath = trim($this->filepath);
232 $this->filepath = preg_replace('/[\\/]+$/', '', $this->filepath); // Remove last /
233 }
234 if (isset($this->fullpath_orig)) {
235 $this->fullpath_orig = trim($this->fullpath_orig);
236 }
237 if (isset($this->description)) {
238 $this->description = trim($this->description);
239 }
240 if (isset($this->keywords)) {
241 $this->keywords = trim($this->keywords);
242 }
243 if (isset($this->cover)) {
244 $this->cover = trim($this->cover);
245 }
246 if (isset($this->gen_or_uploaded)) {
247 $this->gen_or_uploaded = trim($this->gen_or_uploaded);
248 }
249 if (isset($this->fk_user_c)) {
250 $this->fk_user_c = (int) $this->fk_user_c;
251 }
252 if (isset($this->fk_user_m)) {
253 $this->fk_user_m = (int) $this->fk_user_m;
254 }
255 if (isset($this->acl)) {
256 $this->acl = trim($this->acl);
257 }
258 if (isset($this->src_object_type)) {
259 $this->src_object_type = trim($this->src_object_type);
260 }
261 if (empty($this->date_c)) {
262 $this->date_c = dol_now();
263 }
264 if (empty($this->date_m)) {
265 $this->date_m = dol_now();
266 }
267
268 // If ref not defined
269 if (empty($this->ref)) {
270 include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
271 $this->ref = dol_hash($this->filepath.'/'.$this->filename, '3');
272 }
273
274 $maxposition = 0;
275 if (empty($this->position)) {
276 // Get max used
277 $sql = "SELECT MAX(position) as maxposition FROM ".MAIN_DB_PREFIX.$this->table_element;
278 $sql .= " WHERE filepath ='".$this->db->escape($this->filepath)."'";
279
280 $resql = $this->db->query($sql);
281 if ($resql) {
282 $obj = $this->db->fetch_object($resql);
283 $maxposition = (int) $obj->maxposition;
284 } else {
285 $this->errors[] = 'Error '.$this->db->lasterror();
286 return --$error;
287 }
288 $maxposition += 1;
289 } else {
290 $maxposition = $this->position;
291 }
292
293 // Check parameters
294 if (empty($this->filename) || empty($this->filepath)) {
295 $this->errors[] = 'Bad property filename or filepath';
296 return --$error;
297 }
298 if (!isset($this->entity)) {
299 $this->entity = $conf->entity;
300 }
301
302 $extraparams = (!empty($this->extraparams) ? json_encode($this->extraparams) : null);
303 $extraparams = dol_trunc($extraparams, 250);
304
305 // Put here code to add control on parameters values
306 if (!empty($this->agenda_id)) {
307 $this->agenda_id = (int) $this->agenda_id;
308 }
309
310 // Insert request
311 $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'(';
312 $sql .= 'ref,';
313 $sql .= 'label,';
314 $sql .= 'share,';
315 $sql .= 'entity,';
316 $sql .= 'filename,';
317 $sql .= 'filepath,';
318 $sql .= 'fullpath_orig,';
319 $sql .= 'description,';
320 $sql .= 'keywords,';
321 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
322 $sql .= 'content,';
323 }
324 $sql .= 'cover,';
325 $sql .= 'position,';
326 $sql .= 'gen_or_uploaded,';
327 $sql .= 'extraparams,';
328 $sql .= 'date_c,';
329 $sql .= 'tms,';
330 $sql .= 'fk_user_c,';
331 $sql .= 'fk_user_m,';
332 $sql .= 'acl,';
333 $sql .= 'src_object_type,';
334 $sql .= 'src_object_id,';
335 $sql .= 'agenda_id';
336 $sql .= ') VALUES (';
337 $sql .= " '".$this->db->escape($this->ref)."', ";
338 $sql .= ' '.(!isset($this->label) ? 'NULL' : "'".$this->db->escape($this->label)."'").',';
339 $sql .= ' '.(!isset($this->share) ? 'NULL' : "'".$this->db->escape($this->share)."'").',';
340 $sql .= ' '.((int) $this->entity).',';
341 $sql .= ' '.(!isset($this->filename) ? 'NULL' : "'".$this->db->escape($this->filename)."'").',';
342 $sql .= ' '.(!isset($this->filepath) ? 'NULL' : "'".$this->db->escape($this->filepath)."'").',';
343 $sql .= ' '.(!isset($this->fullpath_orig) ? 'NULL' : "'".$this->db->escape($this->fullpath_orig)."'").',';
344 $sql .= ' '.(!isset($this->description) ? 'NULL' : "'".$this->db->escape($this->description)."'").',';
345 $sql .= ' '.(!isset($this->keywords) ? 'NULL' : "'".$this->db->escape($this->keywords)."'").',';
346 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
347 $sql .= ' '.(!isset($this->content) ? 'NULL' : "'".$this->db->escape($this->content)."'").',';
348 }
349 $sql .= ' '.(!isset($this->cover) ? 'NULL' : "'".$this->db->escape($this->cover)."'").',';
350 $sql .= ' '.((int) $maxposition).',';
351 $sql .= ' '.(!isset($this->gen_or_uploaded) ? 'NULL' : "'".$this->db->escape($this->gen_or_uploaded)."'").',';
352 $sql .= ' '.(!isset($extraparams) ? 'NULL' : "'".$this->db->escape($extraparams)."'").',';
353 $sql .= " '".$this->db->idate($this->date_c)."',";
354 $sql .= ' '.(!isset($this->date_m) || dol_strlen((string) $this->date_m) == 0 ? 'NULL' : "'".$this->db->idate($this->date_m)."'").',';
355 $sql .= ' '.(!isset($this->fk_user_c) ? $user->id : $this->fk_user_c).',';
356 $sql .= ' '.(!isset($this->fk_user_m) ? 'NULL' : $this->fk_user_m).',';
357 $sql .= ' '.(!isset($this->acl) ? 'NULL' : "'".$this->db->escape($this->acl)."'").',';
358 $sql .= ' '.(!isset($this->src_object_type) ? 'NULL' : "'".$this->db->escape($this->src_object_type)."'").',';
359 $sql .= ' '.(!isset($this->src_object_id) ? 'NULL' : $this->src_object_id).',';
360 $sql .= ' '.(empty($this->agenda_id) ? 'NULL' : (int) $this->agenda_id);
361 $sql .= ')';
362
363 $this->db->begin();
364
365 $resql = $this->db->query($sql);
366 if (!$resql) {
367 $error++;
368 if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
369 $this->errors[] = 'Error DB_ERROR_RECORD_ALREADY_EXISTS : '.$this->db->lasterror();
370 } else {
371 $this->errors[] = 'Error '.$this->db->lasterror();
372 }
373 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
374 }
375
376 if (!$error) {
377 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
378 $this->position = $maxposition;
379
380 // Triggers
381 if (!$notrigger) {
382 // Call triggers
383 $result = $this->call_trigger(strtoupper(get_class($this)).'_CREATE', $user);
384 if ($result < 0) {
385 $error++;
386 }
387 // End call triggers
388 }
389 }
390
391 // Commit or rollback
392 if ($error) {
393 $this->db->rollback();
394
395 return -1 * $error;
396 } else {
397 $this->db->commit();
398
399 return $this->id;
400 }
401 }
402
416 public function fetch($id, $ref = '', $relativepath = '', $hashoffile = '', $hashforshare = '', $src_object_type = '', $src_object_id = 0, $entity = null)
417 {
418 global $conf;
419
420 dol_syslog(__METHOD__, LOG_DEBUG);
421
422 $sql = 'SELECT';
423 $sql .= ' t.rowid,';
424 $sql .= " t.ref,";
425 $sql .= " t.label,";
426 $sql .= " t.share,";
427 $sql .= " t.entity,";
428 $sql .= " t.filename,";
429 $sql .= " t.filepath,";
430 $sql .= " t.fullpath_orig,";
431 $sql .= " t.description,";
432 $sql .= " t.keywords,";
433 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
434 $sql .= " t.content,";
435 }
436 $sql .= " t.cover,";
437 $sql .= " t.position,";
438 $sql .= " t.gen_or_uploaded,";
439 $sql .= " t.extraparams,";
440 $sql .= " t.date_c,";
441 $sql .= " t.tms as date_m,";
442 $sql .= " t.fk_user_c,";
443 $sql .= " t.fk_user_m,";
444 $sql .= ' t.note_private,';
445 $sql .= ' t.note_public,';
446 $sql .= " t.acl,";
447 $sql .= " t.src_object_type,";
448 $sql .= " t.src_object_id,";
449 $sql .= " t.agenda_id";
450 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
451 $sql .= ' WHERE 1 = 1';
452 /* Fetching this table depends on filepath+filename, it must not depends on entity because filesystem on disk does not know what is Dolibarr entities
453 if (isModEnabled('multicompany')) {
454 $sql .= " AND entity IN (" . getEntity('ecmfiles') . ")";
455 }*/
456 $filterfound = 0;
457 if ($relativepath) {
458 $relativepathwithnoexe = preg_replace('/\.noexe$/', '', $relativepath); // We must never have the .noexe into the database
459 $sql .= " AND t.filepath = '".$this->db->escape(dirname($relativepath))."'";
460 $filename = basename($relativepathwithnoexe);
461 if ($filename != '*') {
462 $sql .= " AND t.filename = '".$this->db->escape($filename)."'";
463 }
464 if (isset($entity)) {
465 $sql .= " AND t.entity = " . (int) $entity;
466 } else {
467 $sql .= " AND t.entity = " . $conf->entity; // unique key include the entity so each company has its own index
468 }
469 $filterfound++;
470 }
471 if (!empty($ref)) { // hash of file path
472 $sql .= " AND t.ref = '".$this->db->escape($ref)."'";
473 if (isset($entity)) {
474 $sql .= " AND t.entity = " . (int) $entity;
475 } else {
476 $sql .= " AND t.entity = " . $conf->entity; // unique key include the entity so each company has its own index
477 }
478 $filterfound++;
479 }
480 if (!empty($hashoffile)) { // hash of content
481 $sql .= " AND t.label = '".$this->db->escape($hashoffile)."'";
482 if (isset($entity)) {
483 $sql .= " AND t.entity = " . (int) $entity;
484 } else {
485 $sql .= " AND t.entity = " . $conf->entity; // unique key include the entity so each company has its own index
486 }
487 $filterfound++;
488 }
489 if (!empty($hashforshare)) {
490 if ($hashforshare != 'shared') {
491 $sql .= " AND t.share = '".$this->db->escape($hashforshare)."'";
492 } else {
493 $sql .= " AND t.share IS NOT NULL AND t.share <> ''";
494 }
495 //$sql .= " AND t.entity = ".$conf->entity; // hashforshare already unique
496 $filterfound++;
497 }
498 if ($src_object_type && $src_object_id) {
499 $sql .= " AND t.src_object_type = '".$this->db->escape($src_object_type)."' AND t.src_object_id = ".((int) $src_object_id);
500 if (isset($entity)) {
501 $sql .= " AND t.entity = " . (int) $entity;
502 } else {
503 $sql .= " AND t.entity = " . $conf->entity; // unique key include the entity so each company has its own index
504 }
505 $filterfound++;
506 }
507 if ($id > 0 || empty($filterfound)) {
508 $sql .= ' AND t.rowid = '.((int) $id); // rowid already unique
509 }
510
511 // Warning: May return several record, and only first one is returned !
512 $this->db->plimit(1); // When we search on src, or on hash of content (hashforfile), we take first one only
513 $this->db->order('t.rowid', 'ASC');
514
515 $resql = $this->db->query($sql);
516 if ($resql) {
517 $numrows = $this->db->num_rows($resql);
518 if ($numrows) {
519 $obj = $this->db->fetch_object($resql);
520
521 $this->id = $obj->rowid;
522 $this->ref = $obj->ref;
523 $this->label = $obj->label;
524 $this->share = $obj->share;
525 $this->entity = $obj->entity;
526 $this->filename = $obj->filename;
527 $this->filepath = $obj->filepath;
528 $this->fullpath_orig = $obj->fullpath_orig;
529 $this->description = $obj->description;
530 $this->keywords = $obj->keywords;
531 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
532 $this->content = $obj->content;
533 }
534 $this->cover = $obj->cover;
535 $this->position = $obj->position;
536 $this->gen_or_uploaded = $obj->gen_or_uploaded;
537 $this->date_c = $this->db->jdate($obj->date_c);
538 $this->date_m = $this->db->jdate($obj->date_m);
539 $this->fk_user_c = $obj->fk_user_c;
540 $this->fk_user_m = $obj->fk_user_m;
541 $this->note_private = $obj->note_private;
542 $this->note_public = $obj->note_public;
543 $this->acl = $obj->acl;
544 $this->src_object_type = $obj->src_object_type;
545 $this->src_object_id = $obj->src_object_id;
546 $this->agenda_id = $obj->agenda_id;
547 $this->extraparams = (isset($obj->extraparams) ? (array) json_decode($obj->extraparams, true) : null);
548 }
549
550 // Retrieve all extrafields for ecm_files
551 // fetch optionals attributes and labels
552 $this->fetch_optionals();
553
554 // $this->fetch_lines();
555
556 $this->db->free($resql);
557
558 if ($numrows) {
559 return 1;
560 } else {
561 return 0;
562 }
563 } else {
564 $this->errors[] = 'Error '.$this->db->lasterror();
565 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
566
567 return -1;
568 }
569 }
570
582 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
583 {
584 dol_syslog(__METHOD__, LOG_DEBUG);
585
586 $sql = 'SELECT';
587 $sql .= ' t.rowid,';
588 $sql .= " t.label,";
589 $sql .= " t.share,";
590 $sql .= " t.entity,";
591 $sql .= " t.filename,";
592 $sql .= " t.filepath,";
593 $sql .= " t.fullpath_orig,";
594 $sql .= " t.description,";
595 $sql .= " t.keywords,";
596 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
597 $sql .= " t.content,";
598 }
599 $sql .= " t.cover,";
600 $sql .= " t.position,";
601 $sql .= " t.gen_or_uploaded,";
602 $sql .= " t.extraparams,";
603 $sql .= " t.date_c,";
604 $sql .= " t.tms as date_m,";
605 $sql .= " t.fk_user_c,";
606 $sql .= " t.fk_user_m,";
607 $sql .= " t.acl,";
608 $sql .= " t.src_object_type,";
609 $sql .= " t.src_object_id,";
610 $sql .= " t.agenda_id";
611 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
612 $sql .= ' WHERE 1 = 1';
613
614 // Manage filter
615 if (is_array($filter)) {
616 $sqlwhere = array();
617 if (count($filter) > 0) {
618 foreach ($filter as $key => $value) {
619 if ($key == 't.src_object_id') {
620 $sqlwhere[] = $this->db->sanitize($key)." = ".((int) $value);
621 } else {
622 $sqlwhere[] = $this->db->sanitize($key)." LIKE '%".$this->db->escape($this->db->escapeforlike($value))."%'";
623 }
624 }
625 }
626 if (count($sqlwhere) > 0) {
627 $sql .= ' AND '.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere);
628 }
629
630 $filter = '';
631 }
632
633 // Manage filter
634 $errormessage = '';
635 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
636 if ($errormessage) {
637 $this->errors[] = $errormessage;
638 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
639 return -1;
640 }
641
642 /* Fetching this table depends on filepath+filename, it must not depends on entity
643 if (isModEnabled('multicompany')) {
644 $sql .= " AND entity IN (" . getEntity('ecmfiles') . ")";
645 }*/
646 if (!empty($sortfield)) {
647 $sql .= $this->db->order($sortfield, $sortorder);
648 }
649 if (!empty($limit)) {
650 $sql .= $this->db->plimit($limit, $offset);
651 }
652
653 $this->lines = array();
654
655 $resql = $this->db->query($sql);
656 if ($resql) {
657 $num = $this->db->num_rows($resql);
658
659 while ($obj = $this->db->fetch_object($resql)) {
660 $line = new EcmFilesLine($this->db);
661
662 $line->id = $obj->rowid;
663 $line->ref = $obj->rowid;
664 $line->label = $obj->label;
665 $line->share = $obj->share;
666 $line->entity = $obj->entity;
667 $line->filename = $obj->filename;
668 $line->filepath = $obj->filepath;
669 $line->fullpath_orig = $obj->fullpath_orig;
670 $line->description = $obj->description;
671 $line->keywords = $obj->keywords;
672 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
673 $line->content = $obj->content;
674 }
675 $line->cover = $obj->cover;
676 $line->position = $obj->position;
677 $line->gen_or_uploaded = $obj->gen_or_uploaded;
678 $line->extraparams = $obj->extraparams;
679 $line->date_c = $this->db->jdate($obj->date_c);
680 $line->date_m = $this->db->jdate($obj->date_m);
681 $line->fk_user_c = $obj->fk_user_c;
682 $line->fk_user_m = $obj->fk_user_m;
683 $line->acl = $obj->acl;
684 $line->src_object_type = $obj->src_object_type;
685 $line->src_object_id = $obj->src_object_id;
686 $line->agenda_id = $obj->agenda_id;
687 $this->lines[] = $line;
688 }
689 $this->db->free($resql);
690
691 return $num;
692 } else {
693 $this->errors[] = 'Error '.$this->db->lasterror();
694 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
695
696 return -1;
697 }
698 }
699
707 public function update(User $user, $notrigger = 0)
708 {
709 global $conf;
710
711 $error = 0;
712
713 dol_syslog(__METHOD__, LOG_DEBUG);
714
715 // Clean parameters
716
717 if (isset($this->ref)) {
718 $this->ref = trim($this->ref);
719 }
720 if (isset($this->label)) {
721 $this->label = trim($this->label);
722 }
723 if (isset($this->share)) {
724 $this->share = trim($this->share);
725 }
726 if (isset($this->entity)) {
727 $this->entity = (int) $this->entity;
728 }
729 if (isset($this->filename)) {
730 $this->filename = preg_replace('/\.noexe$/', '', trim($this->filename));
731 }
732 if (isset($this->filepath)) {
733 $this->filepath = trim($this->filepath);
734 $this->filepath = preg_replace('/[\\/]+$/', '', $this->filepath); // Remove last /
735 }
736 if (isset($this->fullpath_orig)) {
737 $this->fullpath_orig = trim($this->fullpath_orig);
738 }
739 if (isset($this->description)) {
740 $this->description = trim($this->description);
741 }
742 if (isset($this->keywords)) {
743 $this->keywords = trim($this->keywords);
744 }
745 if (isset($this->cover)) {
746 $this->cover = trim($this->cover);
747 }
748 if (isset($this->gen_or_uploaded)) {
749 $this->gen_or_uploaded = trim($this->gen_or_uploaded);
750 }
751 if (isset($this->fk_user_m)) {
752 $this->fk_user_m = (int) $this->fk_user_m;
753 }
754 if (isset($this->acl)) {
755 $this->acl = trim($this->acl);
756 }
757 if (isset($this->src_object_type)) {
758 $this->src_object_type = trim($this->src_object_type);
759 }
760 if (!empty($this->agenda_id)) {
761 $this->agenda_id = (int) $this->agenda_id;
762 }
763 $extraparams = (!empty($this->extraparams) ? json_encode($this->extraparams) : null);
764 $extraparams = dol_trunc($extraparams, 250);
765
766 // Update request
767 $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET';
768 $sql .= " ref = '".$this->db->escape(dol_hash($this->filepath."/".$this->filename, '3'))."',";
769 $sql .= ' label = '.(isset($this->label) ? "'".$this->db->escape($this->label)."'" : "null").',';
770 $sql .= ' share = '.(!empty($this->share) ? "'".$this->db->escape($this->share)."'" : "null").',';
771 $sql .= ' entity = '.(isset($this->entity) ? $this->entity : $conf->entity).',';
772 $sql .= ' filename = '.(isset($this->filename) ? "'".$this->db->escape($this->filename)."'" : "null").',';
773 $sql .= ' filepath = '.(isset($this->filepath) ? "'".$this->db->escape($this->filepath)."'" : "null").',';
774 $sql .= ' fullpath_orig = '.(isset($this->fullpath_orig) ? "'".$this->db->escape($this->fullpath_orig)."'" : "null").',';
775 $sql .= ' description = '.(isset($this->description) ? "'".$this->db->escape($this->description)."'" : "null").',';
776 $sql .= ' keywords = '.(isset($this->keywords) ? "'".$this->db->escape($this->keywords)."'" : "null").',';
777 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
778 $sql .= ' content = '.(isset($this->content) ? "'".$this->db->escape($this->content)."'" : "null").',';
779 }
780 $sql .= ' cover = '.(isset($this->cover) ? "'".$this->db->escape($this->cover)."'" : "null").',';
781 $sql .= ' position = '.(isset($this->position) ? $this->db->escape((string) $this->position) : "0").',';
782 $sql .= ' gen_or_uploaded = '.(isset($this->gen_or_uploaded) ? "'".$this->db->escape($this->gen_or_uploaded)."'" : "null").',';
783 $sql .= ' extraparams = '.(isset($extraparams) ? "'".$this->db->escape($extraparams)."'" : "null").',';
784 $sql .= ' date_c = '.(!isset($this->date_c) || dol_strlen($this->date_c) != 0 ? "'".$this->db->idate($this->date_c)."'" : 'null').',';
785 //$sql .= ' tms = '.(! isset($this->date_m) || dol_strlen((string) $this->date_m) != 0 ? "'".$this->db->idate($this->date_m)."'" : 'null').','; // Field automatically updated
786 $sql .= ' fk_user_m = '.($this->fk_user_m > 0 ? $this->fk_user_m : $user->id).',';
787 $sql .= ' acl = '.(isset($this->acl) ? "'".$this->db->escape($this->acl)."'" : "null").',';
788 $sql .= ' src_object_id = '.($this->src_object_id > 0 ? $this->src_object_id : "null").',';
789 $sql .= ' src_object_type = '.(isset($this->src_object_type) ? "'".$this->db->escape($this->src_object_type)."'" : "null").',';
790 $sql .= ' agenda_id = '.($this->agenda_id > 0 ? (int) $this->agenda_id : "null");
791 $sql .= ' WHERE rowid='.((int) $this->id);
792 $this->db->begin();
793
794 $resql = $this->db->query($sql);
795 if (!$resql) {
796 $error++;
797 $this->errors[] = 'Error '.$this->db->lasterror();
798 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
799 }
800
801 if (!$error) {
802 // Update extrafields
803 $result = $this->insertExtraFields();
804 if ($result < 0) {
805 $error++;
806 }
807 }
808
809 // Triggers
810 if (!$error && !$notrigger) {
811 // Call triggers
812 $result = $this->call_trigger(strtoupper(get_class($this)).'_MODIFY', $user);
813 if ($result < 0) {
814 $error++;
815 } //Do also here what you must do to rollback action if trigger fail
816 // End call triggers
817 }
818
819 // Commit or rollback
820 if ($error) {
821 $this->db->rollback();
822
823 return -1 * $error;
824 } else {
825 $this->db->commit();
826
827 return 1;
828 }
829 }
830
838 public function delete(User $user, $notrigger = 0)
839 {
840 dol_syslog(__METHOD__, LOG_DEBUG);
841
842 $error = 0;
843
844 $this->db->begin();
845
846 // Triggers
847 if (!$notrigger) {
848 // Call triggers
849 $result = $this->call_trigger(strtoupper(get_class($this)).'_DELETE', $user);
850 if ($result < 0) {
851 $error++;
852 } //Do also here what you must do to rollback action if trigger fail
853 // End call triggers
854 }
855
856 // If you need to delete child tables to, you can insert them here
857 if (!$error) {
858 $result = $this->deleteExtraFields();
859 if (!$result) {
860 dol_syslog(get_class($this)."::delete error ".$this->error, LOG_ERR);
861 $error++;
862 }
863 }
864 if (!$error) {
865 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element;
866 $sql .= ' WHERE rowid='.((int) $this->id);
867
868 $resql = $this->db->query($sql);
869 if (!$resql) {
870 $error++;
871 $this->errors[] = 'Error '.$this->db->lasterror();
872 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
873 }
874 }
875
876 // Commit or rollback
877 if ($error) {
878 $this->db->rollback();
879
880 return -1 * $error;
881 } else {
882 $this->db->commit();
883
884 return 1;
885 }
886 }
887
895 public function createFromClone(User $user, $fromid)
896 {
897 dol_syslog(__METHOD__, LOG_DEBUG);
898
899 $error = 0;
900 $object = new EcmFiles($this->db);
901
902 $this->db->begin();
903
904 // Load source object
905 $object->fetch($fromid);
906 // Reset object
907 $object->id = 0;
908
909 // Clear fields
910 // ...
911
912 // Create clone
913 $object->context['createfromclone'] = 'createfromclone';
914 $result = $object->create($user);
915
916 // Other options
917 if ($result < 0) {
918 $error++;
919 $this->errors = $object->errors;
920 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
921 }
922
923 unset($object->context['createfromclone']);
924
925 // End
926 if (!$error) {
927 $this->db->commit();
928
929 return $object->id;
930 } else {
931 $this->db->rollback();
932
933 return -1;
934 }
935 }
936
944 public function updateAfterRename($olddir, $newdir)
945 {
946 $sql = 'UPDATE '.MAIN_DB_PREFIX.'ecm_files SET';
947 $sql .= ' filepath = "'.$this->db->escape($newdir).'"';
948 //$sql .= ', fullpath_orig = "'.$dbs->escape($newdir)."'";
949 $sql .= ' WHERE ';
950 $sql .= ' filepath = "'.$this->db->escape($olddir).'"';
951 // $sql .= ' AND fullpath_orig = "'.$dbs->escape($olddir).'"';
952
953 $this->db->query($sql);
954 }
955
963 public function getTooltipContentArray($params)
964 {
965 global $langs;
966
967 $langs->load('ecm');
968 $datas = [];
969 $nofetch = !empty($params['nofetch']);
970
971 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
972 return ['optimize' => $langs->trans("ShowFile")];
973 }
974 $datas['picto'] = img_picto('', $this->picto, '', 0, 0, 0, '', 'paddingrightonly') . '<u>' . $langs->trans("File") . '</u>';
975 if (!empty($this->filename)) {
976 $datas['name'] = '<br><b>'.$langs->trans('Name').':</b> '.basename($this->filename);
977 }
978 if (!empty($this->ref)) {
979 $datas['ref'] = '<br><b>'.$langs->trans('HashOfFileContent').':</b> '.$this->ref;
980 }
981 if (!empty($this->share)) {
982 $datas['share'] = '<br>'.$langs->trans("FileSharedViaALink");
983 } else {
984 $datas['share'] = '<br>'.$langs->trans("FileNotShared");
985 }
986 if (!empty($this->gen_or_uploaded)) {
987 $datas['gen_or_upload'] = '<br><b>'.$langs->trans('GenOrUpload').':</b> '.$this->gen_or_uploaded;
988 }
989 if (!empty($this->content)) {
990 $datas['content'] = '<br>'.$langs->trans('FileHasAnIndexedTextContent');
991 }
992
993 return $datas;
994 }
995
1006 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $maxlen = 24, $morecss = '')
1007 {
1008 global $conf, $hookmanager, $langs;
1009
1010 if (!empty($conf->dol_no_mouse_hover)) {
1011 $notooltip = 1; // Force disable tooltips
1012 }
1013
1014 $result = '';
1015
1016 $params = [
1017 'id' => $this->id,
1018 'objecttype' => $this->element,
1019 'option' => $option,
1020 'nofetch' => 1,
1021 ];
1022 $classfortooltip = 'classfortooltip';
1023 $dataparams = '';
1024 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1025 $classfortooltip = 'classforajaxtooltip';
1026 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1027 $label = '';
1028 } else {
1029 $label = implode($this->getTooltipContentArray($params));
1030 }
1031
1032 if ($option) {
1033 if ($option == 'facture_fournisseur') {
1034 $tmppath = preg_replace('/^(\d+\/)?fournisseur\/facture\//', '', $this->filepath);
1035 } elseif ($option == 'commande_fournisseur') {
1036 $tmppath = preg_replace('/^(\d+\/)?fournisseur\/commande\//', '', $this->filepath);
1037 } elseif ($option == 'tax-vat') { // Remove part "tax/vat/"
1038 $tmppath = preg_replace('/^(\d+\/)?tax\/vat\//', '', $this->filepath);
1039 } elseif ($option == 'remisecheque') { // Remove part "tax/vat/"
1040 $tmppath = preg_replace('/^bank\/checkdeposits\//', '', $this->filepath);
1041 } else {
1042 if ((int) $this->entity > 1) {
1043 // Remove the part "entityid/commande/" into "entityid/commande/REFXXX" to get only the ref
1044 $tmppath = preg_replace('/^\d+\/[^\/]+\//', '', $this->filepath);
1045 } else {
1046 // Remove the part "commande/" into "commande/REFXXX" to get only the ref
1047 $tmppath = preg_replace('/^[^\/]+\//', '', $this->filepath);
1048 }
1049 }
1050 $url = DOL_URL_ROOT.'/document.php?modulepart='.urlencode($option).'&file='.urlencode($tmppath.'/'.$this->filename).'&entity='.((int) $this->entity);
1051 } else {
1052 $url = DOL_URL_ROOT.'/ecm/file_card.php?id='.$this->id;
1053 }
1054
1055 $linkclose = '';
1056 if (empty($notooltip)) {
1057 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1058 $label = $langs->trans("ShowFile");
1059 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
1060 }
1061 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
1062 $linkclose .= $dataparams.' class="'.$classfortooltip.' '.($morecss ? ' '.$morecss : '').'"';
1063 } else {
1064 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1065 }
1066
1067 $linkstart = '<a href="'.$url.'"';
1068 if (getDolGlobalInt('MAIN_DISABLE_FORCE_SAVEAS') == 2) {
1069 $linkstart .= 'target="_blank" ';
1070 }
1071 $linkstart .= $linkclose.'>';
1072 $linkend = '</a>';
1073
1074 if ($withpicto) {
1075 if (empty($this->filename)) {
1076 $result .= ($linkstart.img_object(($notooltip ? '' : $label), 'label', ($notooltip ? '' : 'class="paddingright"')).$linkend);
1077 } else {
1078 $result .= ($linkstart.img_mime($this->filename, ($notooltip ? '' : dol_escape_htmltag($label, 1)), ($notooltip ? '' : ' paddingright')).$linkend);
1079 }
1080 }
1081 $result .= $linkstart.$this->filename.$linkend;
1082
1083 global $action;
1084 $hookmanager->initHooks(array($this->element . 'dao'));
1085 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1086 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1087 if ($reshook > 0) {
1088 $result = $hookmanager->resPrint;
1089 } else {
1090 $result .= $hookmanager->resPrint;
1091 }
1092
1093 return $result;
1094 }
1095
1102 public function getLibStatut($mode = 0)
1103 {
1104 return $this->LibStatut($this->status, $mode);
1105 }
1106
1107 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1115 public static function LibStatut($status, $mode = 0)
1116 {
1117 // phpcs:enable
1118 global $langs;
1119 return '';
1120 }
1121
1122
1129 public function initAsSpecimen()
1130 {
1131 global $conf, $user;
1132
1133 $this->id = 0;
1134 $this->specimen = 1;
1135 $this->label = '0a1b2c3e4f59999999';
1136 $this->entity = 1;
1137 $this->filename = 'myspecimenfilefile.pdf';
1138 $this->filepath = '/aaa/bbb';
1139 $this->fullpath_orig = 'c:/file on my disk.pdf';
1140 $this->description = 'This is a description of the file';
1141 $this->keywords = 'key1,key2';
1142 $this->content = 'This is the text content of the file';
1143 $this->cover = '1';
1144 $this->position = 5;
1145 $this->gen_or_uploaded = 'uploaded';
1146 $this->extraparams = '';
1147 $this->date_c = (dol_now() - 3600 * 24 * 10);
1148 $this->date_m = '';
1149 $this->fk_user_c = $user->id;
1150 $this->fk_user_m = $user->id;
1151 $this->acl = '';
1152 $this->src_object_type = 'product';
1153 $this->src_object_id = 1;
1154
1155 return 1;
1156 }
1157}
1158
1159
1164{
1168 public $label;
1169
1173 public $entity;
1174
1178 public $filename;
1182 public $filepath;
1186 public $fullpath_orig;
1187
1191 public $description;
1192
1196 public $keywords;
1197
1201 public $content;
1202
1206 public $cover;
1210 public $position;
1214 public $gen_or_uploaded; // can be 'generated', 'uploaded', 'unknown'
1218 public $extraparams;
1222 public $date_c = '';
1226 public $date_m = '';
1227
1231 public $fk_user_c;
1232
1236 public $fk_user_m;
1237
1241 public $acl;
1245 public $src_object_type;
1249 public $src_object_id;
1250}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
print $object position
Definition edit.php:207
$object ref
Definition info.php:90
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
deleteExtraFields()
Delete all extra fields values for the current object.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class to manage ECM files.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
getTooltipContentArray($params)
getTooltipContentArray
getLibStatut($mode=0)
Return the label of the status.
createFromClone(User $user, $fromid)
Load an object from its id and create a new one in database.
update(User $user, $notrigger=0)
Update object into database.
getNomUrl($withpicto=0, $option='', $notooltip=0, $maxlen=24, $morecss='')
Return a link to the object card (with optionally the picto)
fetch($id, $ref='', $relativepath='', $hashoffile='', $hashforshare='', $src_object_type='', $src_object_id=0, $entity=null)
Load object in memory from the database.
__construct(DoliDB $db)
Constructor.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND')
Load object in memory from the database.
static LibStatut($status, $mode=0)
Return the status.
updateAfterRename($olddir, $newdir)
updateAfterRename update entries in ecmfiles if exist to avoid losing info
create(User $user, $notrigger=0)
Create object into database.
Class of an index line of a document.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:171
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_now($mode='gmt')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
dol_hash($chain, $type='0', $nosalt=0, $mode=0)
Returns a hash (non reversible encryption) of a string.