dolibarr 21.0.0-beta
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-2024 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2024 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
57 public $ref;
58
63 public $label;
64
68 public $share;
69
73 public $entity;
74
78 public $filename;
79
83 public $filepath;
84
88 public $fullpath_orig;
89
93 public $description;
94
98 public $keywords;
99
103 public $content;
104
108 public $cover;
109
113 public $position;
114
118 public $gen_or_uploaded;
119
123 public $extraparams;
124
128 public $date_c = '';
129
133 public $date_m = '';
134
138 public $fk_user_c;
139
143 public $fk_user_m;
144
148 public $acl;
149
153 public $src_object_type;
154
158 public $src_object_id;
159
163 public $section_id;
164
165 public $fields = array(
166 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
167 '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"),
168 '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"),
169 '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"),
170 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 50, 'index' => 1),
171 '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"),
172 '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"),
173 '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', ...)"),
174 'src_object_id' => array('type' => 'integer', 'label' => 'SourceID', 'default' => '1', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 90, 'index' => 1, 'comment' => "Source object id"),
175 '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"),
176 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'visible' => 0, 'position' => 110),
177 '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."),
178 '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."),
179 'cover' => array('type' => 'text', 'label' => 'Cover', 'enabled' => 1, 'visible' => 0, 'position' => 130, 'comment' => "is this file a file to use for a cover"),
180 'position' => array('type' => 'integer', 'label' => 'Position', 'default' => '1', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 140, 'index' => 1, 'comment' => "position of file among others"),
181 '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'"),
182 '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"),
183 'date_c' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 170),
184 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 175),
185 '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',),
186 'fk_user_m' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2,),
187 'note_public' => array('type' => 'text', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 155),
188 'note_private' => array('type' => 'text', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 160),
189 'acl' => array('type' => 'text', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 160, 'comment' => "for future permission 'per file'"),
190 );
191
192
198 public function __construct(DoliDB $db)
199 {
200 $this->db = $db;
201 }
202
210 public function create(User $user, $notrigger = 0)
211 {
212 global $conf;
213
214 dol_syslog(__METHOD__, LOG_DEBUG);
215
216 $error = 0;
217
218 // Clean parameters
219 if (isset($this->ref)) {
220 $this->ref = trim($this->ref);
221 }
222 if (isset($this->label)) {
223 $this->label = trim($this->label);
224 }
225 if (isset($this->share)) {
226 $this->share = trim($this->share);
227 }
228 if (isset($this->entity)) {
229 $this->entity = (int) $this->entity;
230 }
231 if (isset($this->filename)) {
232 $this->filename = preg_replace('/\.noexe$/', '', trim($this->filename));
233 }
234 if (isset($this->filepath)) {
235 $this->filepath = trim($this->filepath);
236 $this->filepath = preg_replace('/[\\/]+$/', '', $this->filepath); // Remove last /
237 }
238 if (isset($this->fullpath_orig)) {
239 $this->fullpath_orig = trim($this->fullpath_orig);
240 }
241 if (isset($this->description)) {
242 $this->description = trim($this->description);
243 }
244 if (isset($this->keywords)) {
245 $this->keywords = trim($this->keywords);
246 }
247 if (isset($this->cover)) {
248 $this->cover = trim($this->cover);
249 }
250 if (isset($this->gen_or_uploaded)) {
251 $this->gen_or_uploaded = trim($this->gen_or_uploaded);
252 }
253 if (isset($this->extraparams)) {
254 $this->extraparams = trim($this->extraparams);
255 }
256 if (isset($this->fk_user_c)) {
257 $this->fk_user_c = (int) $this->fk_user_c;
258 }
259 if (isset($this->fk_user_m)) {
260 $this->fk_user_m = (int) $this->fk_user_m;
261 }
262 if (isset($this->acl)) {
263 $this->acl = trim($this->acl);
264 }
265 if (isset($this->src_object_type)) {
266 $this->src_object_type = trim($this->src_object_type);
267 }
268 if (empty($this->date_c)) {
269 $this->date_c = dol_now();
270 }
271 if (empty($this->date_m)) {
272 $this->date_m = dol_now();
273 }
274
275 // If ref not defined
276 if (empty($this->ref)) {
277 include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
278 $this->ref = dol_hash($this->filepath.'/'.$this->filename, '3');
279 }
280
281 $maxposition = 0;
282 if (empty($this->position)) {
283 // Get max used
284 $sql = "SELECT MAX(position) as maxposition FROM ".MAIN_DB_PREFIX.$this->table_element;
285 $sql .= " WHERE filepath ='".$this->db->escape($this->filepath)."'";
286
287 $resql = $this->db->query($sql);
288 if ($resql) {
289 $obj = $this->db->fetch_object($resql);
290 $maxposition = (int) $obj->maxposition;
291 } else {
292 $this->errors[] = 'Error '.$this->db->lasterror();
293 return --$error;
294 }
295 $maxposition += 1;
296 } else {
297 $maxposition = $this->position;
298 }
299
300 // Check parameters
301 if (empty($this->filename) || empty($this->filepath)) {
302 $this->errors[] = 'Bad property filename or filepath';
303 return --$error;
304 }
305 if (!isset($this->entity)) {
306 $this->entity = $conf->entity;
307 }
308 // Put here code to add control on parameters values
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 .= ') VALUES (';
336 $sql .= " '".$this->db->escape($this->ref)."', ";
337 $sql .= ' '.(!isset($this->label) ? 'NULL' : "'".$this->db->escape($this->label)."'").',';
338 $sql .= ' '.(!isset($this->share) ? 'NULL' : "'".$this->db->escape($this->share)."'").',';
339 $sql .= ' '.((int) $this->entity).',';
340 $sql .= ' '.(!isset($this->filename) ? 'NULL' : "'".$this->db->escape($this->filename)."'").',';
341 $sql .= ' '.(!isset($this->filepath) ? 'NULL' : "'".$this->db->escape($this->filepath)."'").',';
342 $sql .= ' '.(!isset($this->fullpath_orig) ? 'NULL' : "'".$this->db->escape($this->fullpath_orig)."'").',';
343 $sql .= ' '.(!isset($this->description) ? 'NULL' : "'".$this->db->escape($this->description)."'").',';
344 $sql .= ' '.(!isset($this->keywords) ? 'NULL' : "'".$this->db->escape($this->keywords)."'").',';
345 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
346 $sql .= ' '.(!isset($this->content) ? 'NULL' : "'".$this->db->escape($this->content)."'").',';
347 }
348 $sql .= ' '.(!isset($this->cover) ? 'NULL' : "'".$this->db->escape($this->cover)."'").',';
349 $sql .= ' '.((int) $maxposition).',';
350 $sql .= ' '.(!isset($this->gen_or_uploaded) ? 'NULL' : "'".$this->db->escape($this->gen_or_uploaded)."'").',';
351 $sql .= ' '.(!isset($this->extraparams) ? 'NULL' : "'".$this->db->escape($this->extraparams)."'").',';
352 $sql .= " '".$this->db->idate($this->date_c)."',";
353 $sql .= ' '.(!isset($this->date_m) || dol_strlen((string) $this->date_m) == 0 ? 'NULL' : "'".$this->db->idate($this->date_m)."'").',';
354 $sql .= ' '.(!isset($this->fk_user_c) ? $user->id : $this->fk_user_c).',';
355 $sql .= ' '.(!isset($this->fk_user_m) ? 'NULL' : $this->fk_user_m).',';
356 $sql .= ' '.(!isset($this->acl) ? 'NULL' : "'".$this->db->escape($this->acl)."'").',';
357 $sql .= ' '.(!isset($this->src_object_type) ? 'NULL' : "'".$this->db->escape($this->src_object_type)."'").',';
358 $sql .= ' '.(!isset($this->src_object_id) ? 'NULL' : $this->src_object_id);
359 $sql .= ')';
360
361 $this->db->begin();
362
363 $resql = $this->db->query($sql);
364 if (!$resql) {
365 $error++;
366 if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
367 $this->errors[] = 'Error DB_ERROR_RECORD_ALREADY_EXISTS : '.$this->db->lasterror();
368 } else {
369 $this->errors[] = 'Error '.$this->db->lasterror();
370 }
371 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
372 }
373
374 if (!$error) {
375 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
376 $this->position = $maxposition;
377
378 // Triggers
379 if (!$notrigger) {
380 // Call triggers
381 $result = $this->call_trigger(strtoupper(get_class($this)).'_CREATE', $user);
382 if ($result < 0) {
383 $error++;
384 }
385 // End call triggers
386 }
387 }
388
389 // Commit or rollback
390 if ($error) {
391 $this->db->rollback();
392
393 return -1 * $error;
394 } else {
395 $this->db->commit();
396
397 return $this->id;
398 }
399 }
400
413 public function fetch($id, $ref = '', $relativepath = '', $hashoffile = '', $hashforshare = '', $src_object_type = '', $src_object_id = 0)
414 {
415 global $conf;
416
417 dol_syslog(__METHOD__, LOG_DEBUG);
418
419 $sql = 'SELECT';
420 $sql .= ' t.rowid,';
421 $sql .= " t.ref,";
422 $sql .= " t.label,";
423 $sql .= " t.share,";
424 $sql .= " t.entity,";
425 $sql .= " t.filename,";
426 $sql .= " t.filepath,";
427 $sql .= " t.fullpath_orig,";
428 $sql .= " t.description,";
429 $sql .= " t.keywords,";
430 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
431 $sql .= " t.content,";
432 }
433 $sql .= " t.cover,";
434 $sql .= " t.position,";
435 $sql .= " t.gen_or_uploaded,";
436 $sql .= " t.extraparams,";
437 $sql .= " t.date_c,";
438 $sql .= " t.tms as date_m,";
439 $sql .= " t.fk_user_c,";
440 $sql .= " t.fk_user_m,";
441 $sql .= ' t.note_private,';
442 $sql .= ' t.note_public,';
443 $sql .= " t.acl,";
444 $sql .= " t.src_object_type,";
445 $sql .= " t.src_object_id";
446 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
447 $sql .= ' WHERE 1 = 1';
448 /* Fetching this table depends on filepath+filename, it must not depends on entity because filesystem on disk does not know what is Dolibarr entities
449 if (isModEnabled('multicompany')) {
450 $sql .= " AND entity IN (" . getEntity('ecmfiles') . ")";
451 }*/
452 $filterfound = 0;
453 if ($relativepath) {
454 $relativepathwithnoexe = preg_replace('/\.noexe$/', '', $relativepath); // We must never have the .noexe into the database
455 $sql .= " AND t.filepath = '".$this->db->escape(dirname($relativepath))."'";
456 $filename = basename($relativepathwithnoexe);
457 if ($filename != '*') {
458 $sql .= " AND t.filename = '".$this->db->escape($filename)."'";
459 }
460 $sql .= " AND t.entity = ".$conf->entity; // unique key include the entity so each company has its own index
461 $filterfound++;
462 }
463 if (!empty($ref)) { // hash of file path
464 $sql .= " AND t.ref = '".$this->db->escape($ref)."'";
465 $sql .= " AND t.entity = ".$conf->entity; // unique key include the entity so each company has its own index
466 $filterfound++;
467 }
468 if (!empty($hashoffile)) { // hash of content
469 $sql .= " AND t.label = '".$this->db->escape($hashoffile)."'";
470 $sql .= " AND t.entity = ".$conf->entity; // unique key include the entity so each company has its own index
471 $filterfound++;
472 }
473 if (!empty($hashforshare)) {
474 if ($hashforshare != 'shared') {
475 $sql .= " AND t.share = '".$this->db->escape($hashforshare)."'";
476 } else {
477 $sql .= " AND t.share IS NOT NULL AND t.share <> ''";
478 }
479 //$sql .= " AND t.entity = ".$conf->entity; // hashforshare already unique
480 $filterfound++;
481 }
482 if ($src_object_type && $src_object_id) {
483 $sql .= " AND t.src_object_type = '".$this->db->escape($src_object_type)."' AND t.src_object_id = ".((int) $src_object_id);
484 $sql .= " AND t.entity = ".((int) $conf->entity);
485 $filterfound++;
486 }
487 if ($id > 0 || empty($filterfound)) {
488 $sql .= ' AND t.rowid = '.((int) $id); // rowid already unique
489 }
490
491 // Warning: May return several record, and only first one is returned !
492 $this->db->plimit(1); // When we search on src, or on hash of content (hashforfile), we take first one only
493 $this->db->order('t.rowid', 'ASC');
494
495 $resql = $this->db->query($sql);
496 if ($resql) {
497 $numrows = $this->db->num_rows($resql);
498 if ($numrows) {
499 $obj = $this->db->fetch_object($resql);
500
501 $this->id = $obj->rowid;
502 $this->ref = $obj->ref;
503 $this->label = $obj->label;
504 $this->share = $obj->share;
505 $this->entity = $obj->entity;
506 $this->filename = $obj->filename;
507 $this->filepath = $obj->filepath;
508 $this->fullpath_orig = $obj->fullpath_orig;
509 $this->description = $obj->description;
510 $this->keywords = $obj->keywords;
511 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
512 $this->content = $obj->content;
513 }
514 $this->cover = $obj->cover;
515 $this->position = $obj->position;
516 $this->gen_or_uploaded = $obj->gen_or_uploaded;
517 $this->extraparams = $obj->extraparams;
518 $this->date_c = $this->db->jdate($obj->date_c);
519 $this->date_m = $this->db->jdate($obj->date_m);
520 $this->fk_user_c = $obj->fk_user_c;
521 $this->fk_user_m = $obj->fk_user_m;
522 $this->note_private = $obj->note_private;
523 $this->note_public = $obj->note_public;
524 $this->acl = $obj->acl;
525 $this->src_object_type = $obj->src_object_type;
526 $this->src_object_id = $obj->src_object_id;
527 }
528
529 // Retrieve all extrafields for ecm_files
530 // fetch optionals attributes and labels
531 $this->fetch_optionals();
532
533 // $this->fetch_lines();
534
535 $this->db->free($resql);
536
537 if ($numrows) {
538 return 1;
539 } else {
540 return 0;
541 }
542 } else {
543 $this->errors[] = 'Error '.$this->db->lasterror();
544 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
545
546 return -1;
547 }
548 }
549
561 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
562 {
563 dol_syslog(__METHOD__, LOG_DEBUG);
564
565 $sql = 'SELECT';
566 $sql .= ' t.rowid,';
567 $sql .= " t.label,";
568 $sql .= " t.share,";
569 $sql .= " t.entity,";
570 $sql .= " t.filename,";
571 $sql .= " t.filepath,";
572 $sql .= " t.fullpath_orig,";
573 $sql .= " t.description,";
574 $sql .= " t.keywords,";
575 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
576 $sql .= " t.content,";
577 }
578 $sql .= " t.cover,";
579 $sql .= " t.position,";
580 $sql .= " t.gen_or_uploaded,";
581 $sql .= " t.extraparams,";
582 $sql .= " t.date_c,";
583 $sql .= " t.tms as date_m,";
584 $sql .= " t.fk_user_c,";
585 $sql .= " t.fk_user_m,";
586 $sql .= " t.acl,";
587 $sql .= " t.src_object_type,";
588 $sql .= " t.src_object_id";
589 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
590 $sql .= ' WHERE 1 = 1';
591
592 // Manage filter
593 if (is_array($filter)) {
594 $sqlwhere = array();
595 if (count($filter) > 0) {
596 foreach ($filter as $key => $value) {
597 if ($key == 't.src_object_id') {
598 $sqlwhere[] = $this->db->sanitize($key)." = ".((int) $value);
599 } else {
600 $sqlwhere[] = $this->db->sanitize($key)." LIKE '%".$this->db->escape($this->db->escapeforlike($value))."%'";
601 }
602 }
603 }
604 if (count($sqlwhere) > 0) {
605 $sql .= ' AND '.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere);
606 }
607
608 $filter = '';
609 }
610
611 // Manage filter
612 $errormessage = '';
613 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
614 if ($errormessage) {
615 $this->errors[] = $errormessage;
616 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
617 return -1;
618 }
619
620 /* Fetching this table depends on filepath+filename, it must not depends on entity
621 if (isModEnabled('multicompany')) {
622 $sql .= " AND entity IN (" . getEntity('ecmfiles') . ")";
623 }*/
624 if (!empty($sortfield)) {
625 $sql .= $this->db->order($sortfield, $sortorder);
626 }
627 if (!empty($limit)) {
628 $sql .= $this->db->plimit($limit, $offset);
629 }
630
631 $this->lines = array();
632
633 $resql = $this->db->query($sql);
634 if ($resql) {
635 $num = $this->db->num_rows($resql);
636
637 while ($obj = $this->db->fetch_object($resql)) {
638 $line = new EcmFilesLine($this->db);
639
640 $line->id = $obj->rowid;
641 $line->ref = $obj->rowid;
642 $line->label = $obj->label;
643 $line->share = $obj->share;
644 $line->entity = $obj->entity;
645 $line->filename = $obj->filename;
646 $line->filepath = $obj->filepath;
647 $line->fullpath_orig = $obj->fullpath_orig;
648 $line->description = $obj->description;
649 $line->keywords = $obj->keywords;
650 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
651 $line->content = $obj->content;
652 }
653 $line->cover = $obj->cover;
654 $line->position = $obj->position;
655 $line->gen_or_uploaded = $obj->gen_or_uploaded;
656 $line->extraparams = $obj->extraparams;
657 $line->date_c = $this->db->jdate($obj->date_c);
658 $line->date_m = $this->db->jdate($obj->date_m);
659 $line->fk_user_c = $obj->fk_user_c;
660 $line->fk_user_m = $obj->fk_user_m;
661 $line->acl = $obj->acl;
662 $line->src_object_type = $obj->src_object_type;
663 $line->src_object_id = $obj->src_object_id;
664 $this->lines[] = $line;
665 }
666 $this->db->free($resql);
667
668 return $num;
669 } else {
670 $this->errors[] = 'Error '.$this->db->lasterror();
671 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
672
673 return -1;
674 }
675 }
676
684 public function update(User $user, $notrigger = 0)
685 {
686 global $conf;
687
688 $error = 0;
689
690 dol_syslog(__METHOD__, LOG_DEBUG);
691
692 // Clean parameters
693
694 if (isset($this->ref)) {
695 $this->ref = trim($this->ref);
696 }
697 if (isset($this->label)) {
698 $this->label = trim($this->label);
699 }
700 if (isset($this->share)) {
701 $this->share = trim($this->share);
702 }
703 if (isset($this->entity)) {
704 $this->entity = (int) $this->entity;
705 }
706 if (isset($this->filename)) {
707 $this->filename = preg_replace('/\.noexe$/', '', trim($this->filename));
708 }
709 if (isset($this->filepath)) {
710 $this->filepath = trim($this->filepath);
711 $this->filepath = preg_replace('/[\\/]+$/', '', $this->filepath); // Remove last /
712 }
713 if (isset($this->fullpath_orig)) {
714 $this->fullpath_orig = trim($this->fullpath_orig);
715 }
716 if (isset($this->description)) {
717 $this->description = trim($this->description);
718 }
719 if (isset($this->keywords)) {
720 $this->keywords = trim($this->keywords);
721 }
722 if (isset($this->cover)) {
723 $this->cover = trim($this->cover);
724 }
725 if (isset($this->gen_or_uploaded)) {
726 $this->gen_or_uploaded = trim($this->gen_or_uploaded);
727 }
728 if (isset($this->extraparams)) {
729 $this->extraparams = trim($this->extraparams);
730 }
731 if (isset($this->fk_user_m)) {
732 $this->fk_user_m = (int) $this->fk_user_m;
733 }
734 if (isset($this->acl)) {
735 $this->acl = trim($this->acl);
736 }
737 if (isset($this->src_object_type)) {
738 $this->src_object_type = trim($this->src_object_type);
739 }
740
741 // Check parameters
742 // Put here code to add a control on parameters values
743
744 // Update request
745 $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET';
746 $sql .= " ref = '".$this->db->escape(dol_hash($this->filepath."/".$this->filename, '3'))."',";
747 $sql .= ' label = '.(isset($this->label) ? "'".$this->db->escape($this->label)."'" : "null").',';
748 $sql .= ' share = '.(!empty($this->share) ? "'".$this->db->escape($this->share)."'" : "null").',';
749 $sql .= ' entity = '.(isset($this->entity) ? $this->entity : $conf->entity).',';
750 $sql .= ' filename = '.(isset($this->filename) ? "'".$this->db->escape($this->filename)."'" : "null").',';
751 $sql .= ' filepath = '.(isset($this->filepath) ? "'".$this->db->escape($this->filepath)."'" : "null").',';
752 $sql .= ' fullpath_orig = '.(isset($this->fullpath_orig) ? "'".$this->db->escape($this->fullpath_orig)."'" : "null").',';
753 $sql .= ' description = '.(isset($this->description) ? "'".$this->db->escape($this->description)."'" : "null").',';
754 $sql .= ' keywords = '.(isset($this->keywords) ? "'".$this->db->escape($this->keywords)."'" : "null").',';
755 if (getDolGlobalString("MAIN_SAVE_FILE_CONTENT_AS_TEXT")) {
756 $sql .= ' content = '.(isset($this->content) ? "'".$this->db->escape($this->content)."'" : "null").',';
757 }
758 $sql .= ' cover = '.(isset($this->cover) ? "'".$this->db->escape($this->cover)."'" : "null").',';
759 $sql .= ' position = '.(isset($this->position) ? $this->db->escape($this->position) : "0").',';
760 $sql .= ' gen_or_uploaded = '.(isset($this->gen_or_uploaded) ? "'".$this->db->escape($this->gen_or_uploaded)."'" : "null").',';
761 $sql .= ' extraparams = '.(isset($this->extraparams) ? "'".$this->db->escape($this->extraparams)."'" : "null").',';
762 $sql .= ' date_c = '.(!isset($this->date_c) || dol_strlen($this->date_c) != 0 ? "'".$this->db->idate($this->date_c)."'" : 'null').',';
763 //$sql .= ' tms = '.(! isset($this->date_m) || dol_strlen((string) $this->date_m) != 0 ? "'".$this->db->idate($this->date_m)."'" : 'null').','; // Field automatically updated
764 $sql .= ' fk_user_m = '.($this->fk_user_m > 0 ? $this->fk_user_m : $user->id).',';
765 $sql .= ' acl = '.(isset($this->acl) ? "'".$this->db->escape($this->acl)."'" : "null").',';
766 $sql .= ' src_object_id = '.($this->src_object_id > 0 ? $this->src_object_id : "null").',';
767 $sql .= ' src_object_type = '.(isset($this->src_object_type) ? "'".$this->db->escape($this->src_object_type)."'" : "null");
768 $sql .= ' WHERE rowid='.((int) $this->id);
769
770 $this->db->begin();
771
772 $resql = $this->db->query($sql);
773 if (!$resql) {
774 $error++;
775 $this->errors[] = 'Error '.$this->db->lasterror();
776 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
777 }
778
779 if (!$error) {
780 // Update extrafields
781 $result = $this->insertExtraFields();
782 if ($result < 0) {
783 $error++;
784 }
785 }
786
787 // Triggers
788 if (!$error && !$notrigger) {
789 // Call triggers
790 $result = $this->call_trigger(strtoupper(get_class($this)).'_MODIFY', $user);
791 if ($result < 0) {
792 $error++;
793 } //Do also here what you must do to rollback action if trigger fail
794 // End call triggers
795 }
796
797 // Commit or rollback
798 if ($error) {
799 $this->db->rollback();
800
801 return -1 * $error;
802 } else {
803 $this->db->commit();
804
805 return 1;
806 }
807 }
808
816 public function delete(User $user, $notrigger = 0)
817 {
818 dol_syslog(__METHOD__, LOG_DEBUG);
819
820 $error = 0;
821
822 $this->db->begin();
823
824 // Triggers
825 if (!$notrigger) {
826 // Call triggers
827 $result = $this->call_trigger(strtoupper(get_class($this)).'_DELETE', $user);
828 if ($result < 0) {
829 $error++;
830 } //Do also here what you must do to rollback action if trigger fail
831 // End call triggers
832 }
833
834 // If you need to delete child tables to, you can insert them here
835 if (!$error) {
836 $result = $this->deleteExtraFields();
837 if (!$result) {
838 dol_syslog(get_class($this)."::delete error ".$this->error, LOG_ERR);
839 $error++;
840 }
841 }
842 if (!$error) {
843 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element;
844 $sql .= ' WHERE rowid='.((int) $this->id);
845
846 $resql = $this->db->query($sql);
847 if (!$resql) {
848 $error++;
849 $this->errors[] = 'Error '.$this->db->lasterror();
850 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
851 }
852 }
853
854 // Commit or rollback
855 if ($error) {
856 $this->db->rollback();
857
858 return -1 * $error;
859 } else {
860 $this->db->commit();
861
862 return 1;
863 }
864 }
865
873 public function createFromClone(User $user, $fromid)
874 {
875 dol_syslog(__METHOD__, LOG_DEBUG);
876
877 $error = 0;
878 $object = new EcmFiles($this->db);
879
880 $this->db->begin();
881
882 // Load source object
883 $object->fetch($fromid);
884 // Reset object
885 $object->id = 0;
886
887 // Clear fields
888 // ...
889
890 // Create clone
891 $object->context['createfromclone'] = 'createfromclone';
892 $result = $object->create($user);
893
894 // Other options
895 if ($result < 0) {
896 $error++;
897 $this->errors = $object->errors;
898 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
899 }
900
901 unset($object->context['createfromclone']);
902
903 // End
904 if (!$error) {
905 $this->db->commit();
906
907 return $object->id;
908 } else {
909 $this->db->rollback();
910
911 return -1;
912 }
913 }
914
922 public function updateAfterRename($olddir, $newdir)
923 {
924 $sql = 'UPDATE '.MAIN_DB_PREFIX.'ecm_files SET';
925 $sql .= ' filepath = "'.$this->db->escape($newdir).'"';
926 //$sql .= ', fullpath_orig = "'.$dbs->escape($newdir)."'";
927 $sql .= ' WHERE ';
928 $sql .= ' filepath = "'.$this->db->escape($olddir).'"';
929 // $sql .= ' AND fullpath_orig = "'.$dbs->escape($olddir).'"';
930
931 $this->db->query($sql);
932 }
933
941 public function getTooltipContentArray($params)
942 {
943 global $langs;
944
945 $langs->load('ecm');
946 $datas = [];
947 $nofetch = !empty($params['nofetch']);
948
949 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
950 return ['optimize' => $langs->trans("ShowFile")];
951 }
952 $datas['picto'] = img_picto('', $this->picto, '', 0, 0, 0, '', 'paddingrightonly') . '<u>' . $langs->trans("File") . '</u>';
953 if (!empty($this->filename)) {
954 $datas['name'] = '<br><b>'.$langs->trans('Name').':</b> '.basename($this->filename);
955 }
956 if (!empty($this->ref)) {
957 $datas['ref'] = '<br><b>'.$langs->trans('HashOfFileContent').':</b> '.$this->ref;
958 }
959 if (!empty($this->share)) {
960 $datas['share'] = '<br>'.$langs->trans("FileSharedViaALink");
961 } else {
962 $datas['share'] = '<br>'.$langs->trans("FileNotShared");
963 }
964 if (!empty($this->gen_or_uploaded)) {
965 $datas['gen_or_upload'] = '<br><b>'.$langs->trans('GenOrUpload').':</b> '.$this->gen_or_uploaded;
966 }
967 if (!empty($this->content)) {
968 $datas['content'] = '<br>'.$langs->trans('FileHasAnIndexedTextContent');
969 }
970
971 return $datas;
972 }
973
984 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $maxlen = 24, $morecss = '')
985 {
986 global $conf, $hookmanager, $langs;
987
988 if (!empty($conf->dol_no_mouse_hover)) {
989 $notooltip = 1; // Force disable tooltips
990 }
991
992 $result = '';
993
994 $params = [
995 'id' => $this->id,
996 'objecttype' => $this->element,
997 'option' => $option,
998 'nofetch' => 1,
999 ];
1000 $classfortooltip = 'classfortooltip';
1001 $dataparams = '';
1002 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1003 $classfortooltip = 'classforajaxtooltip';
1004 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1005 $label = '';
1006 } else {
1007 $label = implode($this->getTooltipContentArray($params));
1008 }
1009
1010 if ($option) {
1011 if ($option == 'facture_fournisseur') {
1012 $tmppath = preg_replace('/^fournisseur\/facture\//', '', $this->filepath);
1013 } elseif ($option == 'commande_fournisseur') {
1014 $tmppath = preg_replace('/^fournisseur\/commande\//', '', $this->filepath);
1015 } else {
1016 $tmppath = preg_replace('/^[^\/]+\//', '', $this->filepath);
1017 }
1018 $url = DOL_URL_ROOT.'/document.php?modulepart='.urlencode($option).'&file='.urlencode($tmppath.'/'.$this->filename).'&entity='.$this->entity;
1019 } else {
1020 $url = DOL_URL_ROOT.'/ecm/file_card.php?id='.$this->id;
1021 }
1022
1023 $linkclose = '';
1024 if (empty($notooltip)) {
1025 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1026 $label = $langs->trans("ShowFile");
1027 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1028 }
1029 $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
1030 $linkclose .= $dataparams.' class="'.$classfortooltip.' '.($morecss ? ' '.$morecss : '').'"';
1031 } else {
1032 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1033 }
1034
1035 $linkstart = '<a href="'.$url.'"';
1036 if (getDolGlobalInt('MAIN_DISABLE_FORCE_SAVEAS') == 2) {
1037 $linkstart .= 'target="_blank" ';
1038 }
1039 $linkstart .= $linkclose.'>';
1040 $linkend = '</a>';
1041
1042 if ($withpicto) {
1043 if (empty($this->filename)) {
1044 $result .= ($linkstart.img_object(($notooltip ? '' : $label), 'label', ($notooltip ? '' : 'class="paddingright"')).$linkend);
1045 } else {
1046 $result .= ($linkstart.img_mime($this->filename, ($notooltip ? '' : dol_escape_htmltag($label, 1)), ($notooltip ? '' : ' paddingright')).$linkend);
1047 }
1048 if ($withpicto != 2) {
1049 $result .= ' ';
1050 }
1051 }
1052 $result .= $linkstart.$this->filename.$linkend;
1053
1054 global $action;
1055 $hookmanager->initHooks(array($this->element . 'dao'));
1056 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1057 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1058 if ($reshook > 0) {
1059 $result = $hookmanager->resPrint;
1060 } else {
1061 $result .= $hookmanager->resPrint;
1062 }
1063
1064 return $result;
1065 }
1066
1073 public function getLibStatut($mode = 0)
1074 {
1075 return $this->LibStatut($this->status, $mode);
1076 }
1077
1078 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1086 public static function LibStatut($status, $mode = 0)
1087 {
1088 // phpcs:enable
1089 global $langs;
1090 return '';
1091 }
1092
1093
1100 public function initAsSpecimen()
1101 {
1102 global $conf, $user;
1103
1104 $this->id = 0;
1105 $this->specimen = 1;
1106 $this->label = '0a1b2c3e4f59999999';
1107 $this->entity = 1;
1108 $this->filename = 'myspecimenfilefile.pdf';
1109 $this->filepath = '/aaa/bbb';
1110 $this->fullpath_orig = 'c:/file on my disk.pdf';
1111 $this->description = 'This is a description of the file';
1112 $this->keywords = 'key1,key2';
1113 $this->content = 'This is the text content of the file';
1114 $this->cover = '1';
1115 $this->position = 5;
1116 $this->gen_or_uploaded = 'uploaded';
1117 $this->extraparams = '';
1118 $this->date_c = (dol_now() - 3600 * 24 * 10);
1119 $this->date_m = '';
1120 $this->fk_user_c = $user->id;
1121 $this->fk_user_m = $user->id;
1122 $this->acl = '';
1123 $this->src_object_type = 'product';
1124 $this->src_object_id = 1;
1125
1126 return 1;
1127 }
1128}
1129
1130
1135{
1139 public $label;
1140
1144 public $entity;
1145
1149 public $filename;
1153 public $filepath;
1157 public $fullpath_orig;
1158
1162 public $description;
1163
1167 public $keywords;
1168
1172 public $content;
1173
1177 public $cover;
1181 public $position;
1185 public $gen_or_uploaded; // can be 'generated', 'uploaded', 'unknown'
1189 public $extraparams;
1193 public $date_c = '';
1197 public $date_m = '';
1198
1202 public $fk_user_c;
1203
1207 public $fk_user_m;
1208
1212 public $acl;
1216 public $src_object_type;
1220 public $src_object_id;
1221}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
print $object position
Definition edit.php:204
$object ref
Definition info.php:89
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.
call_trigger($triggerName, $user)
Call trigger based on this instance.
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)
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.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
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
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
dol_hash($chain, $type='0', $nosalt=0)
Returns a hash (non reversible encryption) of a string.