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 Frédéric France <frederic.france@netlogic.fr> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 3 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program. If not, see <https://www.gnu.org/licenses/>. 21 */ 22 23/** 24 * \file htdocs/ecm/class/ecmfiles.class.php 25 * \ingroup ecm 26 * \brief Class to manage ECM Files (Create/Read/Update/Delete) 27 */ 28 29// Put here all includes required by your class file 30require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; 31 32/** 33 * Class to manage ECM files 34 */ 35class EcmFiles extends CommonObject 36{ 37 /** 38 * @var string Id to identify managed objects 39 */ 40 public $element = 'ecmfiles'; 41 42 /** 43 * @var string Name of table without prefix where object is stored 44 */ 45 public $table_element = 'ecm_files'; 46 47 /** 48 * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png 49 */ 50 public $picto = 'folder-open'; 51 52 /** 53 * @var string Ref hash of file path 54 */ 55 public $ref; 56 57 /** 58 * hash of file content (md5_file(dol_osencode($destfull)) 59 * @var string Ecm Files label 60 */ 61 public $label; 62 63 /** 64 * @var string hash for file sharing, empty by default (example: getRandomPassword(true)) 65 */ 66 public $share; 67 68 /** 69 * @var int Entity 70 */ 71 public $entity; 72 73 /** 74 * @var string filename, Note: Into ecm database record, the entry $filename never ends with .noexe 75 */ 76 public $filename; 77 78 /** 79 * @var string filepath 80 */ 81 public $filepath; 82 83 /** 84 * @var string fullpath origin 85 */ 86 public $fullpath_orig; 87 88 /** 89 * @var string description 90 */ 91 public $description; 92 93 /** 94 * @var string keywords 95 */ 96 public $keywords; 97 98 /** 99 * @var string cover 100 */ 101 public $cover; 102 103 /** 104 * @var int position 105 */ 106 public $position; 107 108 /** 109 * @var string can be 'generated', 'uploaded', 'unknown' 110 */ 111 public $gen_or_uploaded; 112 113 /** 114 * @var string extraparams 115 */ 116 public $extraparams; 117 118 /** 119 * @var int|string date create 120 */ 121 public $date_c = ''; 122 123 /** 124 * @var int|string date modify 125 */ 126 public $date_m = ''; 127 128 /** 129 * @var int ID 130 */ 131 public $fk_user_c; 132 133 /** 134 * @var int ID 135 */ 136 public $fk_user_m; 137 138 /** 139 * @var string acl 140 */ 141 public $acl; 142 143 /** 144 * @var string src object type 145 */ 146 public $src_object_type; 147 148 /** 149 * @var int src object id 150 */ 151 public $src_object_id; 152 153 /** 154 * @var int section_id ID of section = ID of EcmDirectory, directory of manual ECM (not stored into database) 155 */ 156 public $section_id; 157 158 159 160 /** 161 * Constructor 162 * 163 * @param DoliDb $db Database handler 164 */ 165 public function __construct(DoliDB $db) 166 { 167 $this->db = $db; 168 } 169 170 /** 171 * Create object into database 172 * 173 * @param User $user User that creates 174 * @param bool $notrigger false=launch triggers after, true=disable triggers 175 * @return int <0 if KO, Id of created object if OK 176 */ 177 public function create(User $user, $notrigger = false) 178 { 179 global $conf; 180 181 dol_syslog(__METHOD__, LOG_DEBUG); 182 183 $error = 0; 184 185 // Clean parameters 186 if (isset($this->ref)) { 187 $this->ref = trim($this->ref); 188 } 189 if (isset($this->label)) { 190 $this->label = trim($this->label); 191 } 192 if (isset($this->share)) { 193 $this->share = trim($this->share); 194 } 195 if (isset($this->entity)) { 196 $this->entity = (int) $this->entity; 197 } 198 if (isset($this->filename)) { 199 $this->filename = preg_replace('/\.noexe$/', '', trim($this->filename)); 200 } 201 if (isset($this->filepath)) { 202 $this->filepath = trim($this->filepath); 203 $this->filepath = preg_replace('/[\\/]+$/', '', $this->filepath); // Remove last / 204 } 205 if (isset($this->fullpath_orig)) { 206 $this->fullpath_orig = trim($this->fullpath_orig); 207 } 208 if (isset($this->description)) { 209 $this->description = trim($this->description); 210 } 211 if (isset($this->keywords)) { 212 $this->keywords = trim($this->keywords); 213 } 214 if (isset($this->cover)) { 215 $this->cover = trim($this->cover); 216 } 217 if (isset($this->gen_or_uploaded)) { 218 $this->gen_or_uploaded = trim($this->gen_or_uploaded); 219 } 220 if (isset($this->extraparams)) { 221 $this->extraparams = trim($this->extraparams); 222 } 223 if (isset($this->fk_user_c)) { 224 $this->fk_user_c = (int) $this->fk_user_c; 225 } 226 if (isset($this->fk_user_m)) { 227 $this->fk_user_m = (int) $this->fk_user_m; 228 } 229 if (isset($this->acl)) { 230 $this->acl = trim($this->acl); 231 } 232 if (isset($this->src_object_type)) { 233 $this->src_object_type = trim($this->src_object_type); 234 } 235 if (empty($this->date_c)) { 236 $this->date_c = dol_now(); 237 } 238 if (empty($this->date_m)) { 239 $this->date_m = dol_now(); 240 } 241 242 // If ref not defined 243 $ref = ''; 244 if (!empty($this->ref)) { 245 $ref = $this->ref; 246 } else { 247 include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; 248 $ref = dol_hash($this->filepath.'/'.$this->filename, 3); 249 } 250 251 $maxposition = 0; 252 if (empty($this->position)) { 253 // Get max used 254 $sql = "SELECT MAX(position) as maxposition FROM ".MAIN_DB_PREFIX.$this->table_element; 255 $sql .= " WHERE filepath ='".$this->db->escape($this->filepath)."'"; 256 257 $resql = $this->db->query($sql); 258 if ($resql) { 259 $obj = $this->db->fetch_object($resql); 260 $maxposition = (int) $obj->maxposition; 261 } else { 262 $this->errors[] = 'Error '.$this->db->lasterror(); 263 return --$error; 264 } 265 $maxposition = $maxposition + 1; 266 } else { 267 $maxposition = $this->position; 268 } 269 270 // Check parameters 271 if (empty($this->filename) || empty($this->filepath)) { 272 $this->errors[] = 'Bad property filename or filepath'; 273 return --$error; 274 } 275 if (!isset($this->entity)) { 276 $this->entity = $conf->entity; 277 } 278 // Put here code to add control on parameters values 279 280 // Insert request 281 $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'('; 282 $sql .= 'ref,'; 283 $sql .= 'label,'; 284 $sql .= 'share,'; 285 $sql .= 'entity,'; 286 $sql .= 'filename,'; 287 $sql .= 'filepath,'; 288 $sql .= 'fullpath_orig,'; 289 $sql .= 'description,'; 290 $sql .= 'keywords,'; 291 $sql .= 'cover,'; 292 $sql .= 'position,'; 293 $sql .= 'gen_or_uploaded,'; 294 $sql .= 'extraparams,'; 295 $sql .= 'date_c,'; 296 $sql .= 'tms,'; 297 $sql .= 'fk_user_c,'; 298 $sql .= 'fk_user_m,'; 299 $sql .= 'acl,'; 300 $sql .= 'src_object_type,'; 301 $sql .= 'src_object_id'; 302 $sql .= ') VALUES ('; 303 $sql .= " '".$this->db->escape($ref)."', "; 304 $sql .= ' '.(!isset($this->label) ? 'NULL' : "'".$this->db->escape($this->label)."'").','; 305 $sql .= ' '.(!isset($this->share) ? 'NULL' : "'".$this->db->escape($this->share)."'").','; 306 $sql .= ' '.$this->entity.','; 307 $sql .= ' '.(!isset($this->filename) ? 'NULL' : "'".$this->db->escape($this->filename)."'").','; 308 $sql .= ' '.(!isset($this->filepath) ? 'NULL' : "'".$this->db->escape($this->filepath)."'").','; 309 $sql .= ' '.(!isset($this->fullpath_orig) ? 'NULL' : "'".$this->db->escape($this->fullpath_orig)."'").','; 310 $sql .= ' '.(!isset($this->description) ? 'NULL' : "'".$this->db->escape($this->description)."'").','; 311 $sql .= ' '.(!isset($this->keywords) ? 'NULL' : "'".$this->db->escape($this->keywords)."'").','; 312 $sql .= ' '.(!isset($this->cover) ? 'NULL' : "'".$this->db->escape($this->cover)."'").','; 313 $sql .= ' '.$maxposition.','; 314 $sql .= ' '.(!isset($this->gen_or_uploaded) ? 'NULL' : "'".$this->db->escape($this->gen_or_uploaded)."'").','; 315 $sql .= ' '.(!isset($this->extraparams) ? 'NULL' : "'".$this->db->escape($this->extraparams)."'").','; 316 $sql .= ' '."'".$this->db->idate($this->date_c)."'".','; 317 $sql .= ' '.(!isset($this->date_m) || dol_strlen($this->date_m) == 0 ? 'NULL' : "'".$this->db->idate($this->date_m)."'").','; 318 $sql .= ' '.(!isset($this->fk_user_c) ? $user->id : $this->fk_user_c).','; 319 $sql .= ' '.(!isset($this->fk_user_m) ? 'NULL' : $this->fk_user_m).','; 320 $sql .= ' '.(!isset($this->acl) ? 'NULL' : "'".$this->db->escape($this->acl)."'").','; 321 $sql .= ' '.(!isset($this->src_object_type) ? 'NULL' : "'".$this->db->escape($this->src_object_type)."'").','; 322 $sql .= ' '.(!isset($this->src_object_id) ? 'NULL' : $this->src_object_id); 323 $sql .= ')'; 324 325 $this->db->begin(); 326 327 $resql = $this->db->query($sql); 328 if (!$resql) { 329 $error++; 330 $this->errors[] = 'Error '.$this->db->lasterror(); 331 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR); 332 } 333 334 if (!$error) { 335 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element); 336 $this->position = $maxposition; 337 338 // Triggers 339 if (!$notrigger) { 340 // Call triggers 341 $result = $this->call_trigger(strtoupper(get_class($this)).'_CREATE', $user); 342 if ($result < 0) { 343 $error++; 344 } 345 // End call triggers 346 } 347 } 348 349 // Commit or rollback 350 if ($error) { 351 $this->db->rollback(); 352 353 return -1 * $error; 354 } else { 355 $this->db->commit(); 356 357 return $this->id; 358 } 359 } 360 361 /** 362 * Load object in memory from the database 363 * 364 * @param int $id Id object 365 * @param string $ref Hash of file name (filename+filepath). Not always defined on some version. 366 * @param string $relativepath Relative path of file from document directory. Example: 'path/path2/file' or 'path/path2/*' 367 * @param string $hashoffile Hash of file content. Take the first one found if same file is at different places. This hash will also change if file content is changed. 368 * @param string $hashforshare Hash of file sharing. 369 * @param string $src_object_type src_object_type to search (value of object->table_element) 370 * @param string $src_object_id src_object_id to search 371 * @return int <0 if KO, 0 if not found, >0 if OK 372 */ 373 public function fetch($id, $ref = '', $relativepath = '', $hashoffile = '', $hashforshare = '', $src_object_type = '', $src_object_id = 0) 374 { 375 global $conf; 376 377 dol_syslog(__METHOD__, LOG_DEBUG); 378 379 $sql = 'SELECT'; 380 $sql .= ' t.rowid,'; 381 $sql .= " t.ref,"; 382 $sql .= " t.label,"; 383 $sql .= " t.share,"; 384 $sql .= " t.entity,"; 385 $sql .= " t.filename,"; 386 $sql .= " t.filepath,"; 387 $sql .= " t.fullpath_orig,"; 388 $sql .= " t.description,"; 389 $sql .= " t.keywords,"; 390 $sql .= " t.cover,"; 391 $sql .= " t.position,"; 392 $sql .= " t.gen_or_uploaded,"; 393 $sql .= " t.extraparams,"; 394 $sql .= " t.date_c,"; 395 $sql .= " t.tms as date_m,"; 396 $sql .= " t.fk_user_c,"; 397 $sql .= " t.fk_user_m,"; 398 $sql .= ' t.note_private,'; 399 $sql .= ' t.note_public,'; 400 $sql .= " t.acl,"; 401 $sql .= " t.src_object_type,"; 402 $sql .= " t.src_object_id"; 403 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; 404 $sql .= ' WHERE 1 = 1'; 405 /* Fetching this table depends on filepath+filename, it must not depends on entity because filesystem on disk does not know what is Dolibarr entities 406 if (! empty($conf->multicompany->enabled)) { 407 $sql .= " AND entity IN (" . getEntity('ecmfiles') . ")"; 408 }*/ 409 if ($relativepath) { 410 $relativepathwithnoexe = preg_replace('/\.noexe$/', '', $relativepath); // We must never have the .noexe into the database 411 $sql .= " AND t.filepath = '".$this->db->escape(dirname($relativepath))."'"; 412 $filename = basename($relativepathwithnoexe); 413 if ($filename != '*') { 414 $sql .= " AND t.filename = '".$this->db->escape($filename)."'"; 415 } 416 $sql .= " AND t.entity = ".$conf->entity; // unique key include the entity so each company has its own index 417 } elseif (!empty($ref)) { // hash of file path 418 $sql .= " AND t.ref = '".$this->db->escape($ref)."'"; 419 $sql .= " AND t.entity = ".$conf->entity; // unique key include the entity so each company has its own index 420 } elseif (!empty($hashoffile)) { // hash of content 421 $sql .= " AND t.label = '".$this->db->escape($hashoffile)."'"; 422 $sql .= " AND t.entity = ".$conf->entity; // unique key include the entity so each company has its own index 423 } elseif (!empty($hashforshare)) { 424 $sql .= " AND t.share = '".$this->db->escape($hashforshare)."'"; 425 //$sql .= " AND t.entity = ".$conf->entity; // hashforshare already unique 426 } elseif ($src_object_type && $src_object_id) { 427 // Warning: May return several record, and only first one is returned ! 428 $sql .= " AND t.src_object_type = '".$this->db->escape($src_object_type)."' AND t.src_object_id = ".((int) $src_object_id); 429 $sql .= " AND t.entity = ".$conf->entity; 430 } else { 431 $sql .= ' AND t.rowid = '.((int) $id); // rowid already unique 432 } 433 434 $this->db->plimit(1); // When we search on src or on hash of content (hashforfile) to solve hash conflict when several files has same content, we take first one only 435 $this->db->order('t.rowid', 'ASC'); 436 437 $resql = $this->db->query($sql); 438 if ($resql) { 439 $numrows = $this->db->num_rows($resql); 440 if ($numrows) { 441 $obj = $this->db->fetch_object($resql); 442 443 $this->id = $obj->rowid; 444 $this->ref = $obj->ref; 445 $this->label = $obj->label; 446 $this->share = $obj->share; 447 $this->entity = $obj->entity; 448 $this->filename = $obj->filename; 449 $this->filepath = $obj->filepath; 450 $this->fullpath_orig = $obj->fullpath_orig; 451 $this->description = $obj->description; 452 $this->keywords = $obj->keywords; 453 $this->cover = $obj->cover; 454 $this->position = $obj->position; 455 $this->gen_or_uploaded = $obj->gen_or_uploaded; 456 $this->extraparams = $obj->extraparams; 457 $this->date_c = $this->db->jdate($obj->date_c); 458 $this->date_m = $this->db->jdate($obj->date_m); 459 $this->fk_user_c = $obj->fk_user_c; 460 $this->fk_user_m = $obj->fk_user_m; 461 $this->note_private = $obj->note_private; 462 $this->note_public = $obj->note_public; 463 $this->acl = $obj->acl; 464 $this->src_object_type = $obj->src_object_type; 465 $this->src_object_id = $obj->src_object_id; 466 } 467 468 // Retrieve all extrafields for ecm_files 469 // fetch optionals attributes and labels 470 $this->fetch_optionals(); 471 472 // $this->fetch_lines(); 473 474 $this->db->free($resql); 475 476 if ($numrows) { 477 return 1; 478 } else { 479 return 0; 480 } 481 } else { 482 $this->errors[] = 'Error '.$this->db->lasterror(); 483 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR); 484 485 return -1; 486 } 487 } 488 489 /** 490 * Load object in memory from the database 491 * 492 * @param string $sortorder Sort Order 493 * @param string $sortfield Sort field 494 * @param int $limit offset limit 495 * @param int $offset offset limit 496 * @param array $filter filter array 497 * @param string $filtermode filter mode (AND or OR) 498 * 499 * @return int <0 if KO, >0 if OK 500 */ 501 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') 502 { 503 dol_syslog(__METHOD__, LOG_DEBUG); 504 505 $sql = 'SELECT'; 506 $sql .= ' t.rowid,'; 507 $sql .= " t.label,"; 508 $sql .= " t.share,"; 509 $sql .= " t.entity,"; 510 $sql .= " t.filename,"; 511 $sql .= " t.filepath,"; 512 $sql .= " t.fullpath_orig,"; 513 $sql .= " t.description,"; 514 $sql .= " t.keywords,"; 515 $sql .= " t.cover,"; 516 $sql .= " t.position,"; 517 $sql .= " t.gen_or_uploaded,"; 518 $sql .= " t.extraparams,"; 519 $sql .= " t.date_c,"; 520 $sql .= " t.tms as date_m,"; 521 $sql .= " t.fk_user_c,"; 522 $sql .= " t.fk_user_m,"; 523 $sql .= " t.acl,"; 524 $sql .= " t.src_object_type,"; 525 $sql .= " t.src_object_id"; 526 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; 527 528 // Manage filter 529 $sqlwhere = array(); 530 if (count($filter) > 0) { 531 foreach ($filter as $key => $value) { 532 if ($key == 't.src_object_id') { 533 $sqlwhere[] = $key.' = '.((int) $value); 534 } else { 535 $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; 536 } 537 } 538 } 539 $sql .= ' WHERE 1 = 1'; 540 /* Fetching this table depends on filepath+filename, it must not depends on entity 541 if (! empty($conf->multicompany->enabled)) { 542 $sql .= " AND entity IN (" . getEntity('ecmfiles') . ")"; 543 }*/ 544 if (count($sqlwhere) > 0) { 545 $sql .= ' AND '.implode(' '.$filtermode.' ', $sqlwhere); 546 } 547 if (!empty($sortfield)) { 548 $sql .= $this->db->order($sortfield, $sortorder); 549 } 550 if (!empty($limit)) { 551 $sql .= ' '.$this->db->plimit($limit, $offset); 552 } 553 554 $this->lines = array(); 555 556 $resql = $this->db->query($sql); 557 if ($resql) { 558 $num = $this->db->num_rows($resql); 559 560 while ($obj = $this->db->fetch_object($resql)) { 561 $line = new EcmfilesLine(); 562 563 $line->id = $obj->rowid; 564 $line->ref = $obj->ref; 565 $line->label = $obj->label; 566 $line->share = $obj->share; 567 $line->entity = $obj->entity; 568 $line->filename = $obj->filename; 569 $line->filepath = $obj->filepath; 570 $line->fullpath_orig = $obj->fullpath_orig; 571 $line->description = $obj->description; 572 $line->keywords = $obj->keywords; 573 $line->cover = $obj->cover; 574 $line->position = $obj->position; 575 $line->gen_or_uploaded = $obj->gen_or_uploaded; 576 $line->extraparams = $obj->extraparams; 577 $line->date_c = $this->db->jdate($obj->date_c); 578 $line->date_m = $this->db->jdate($obj->date_m); 579 $line->fk_user_c = $obj->fk_user_c; 580 $line->fk_user_m = $obj->fk_user_m; 581 $line->acl = $obj->acl; 582 $line->src_object_type = $obj->src_object_type; 583 $line->src_object_id = $obj->src_object_id; 584 $this->lines[] = $line; 585 } 586 $this->db->free($resql); 587 588 return $num; 589 } else { 590 $this->errors[] = 'Error '.$this->db->lasterror(); 591 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR); 592 593 return -1; 594 } 595 } 596 597 /** 598 * Update object into database 599 * 600 * @param User $user User that modifies 601 * @param bool $notrigger false=launch triggers after, true=disable triggers 602 * 603 * @return int <0 if KO, >0 if OK 604 */ 605 public function update(User $user, $notrigger = false) 606 { 607 global $conf; 608 609 $error = 0; 610 611 dol_syslog(__METHOD__, LOG_DEBUG); 612 613 // Clean parameters 614 615 if (isset($this->ref)) { 616 $this->ref = trim($this->ref); 617 } 618 if (isset($this->label)) { 619 $this->label = trim($this->label); 620 } 621 if (isset($this->share)) { 622 $this->share = trim($this->share); 623 } 624 if (isset($this->entity)) { 625 $this->entity = trim($this->entity); 626 } 627 if (isset($this->filename)) { 628 $this->filename = preg_replace('/\.noexe$/', '', trim($this->filename)); 629 } 630 if (isset($this->filepath)) { 631 $this->filepath = trim($this->filepath); 632 $this->filepath = preg_replace('/[\\/]+$/', '', $this->filepath); // Remove last / 633 } 634 if (isset($this->fullpath_orig)) { 635 $this->fullpath_orig = trim($this->fullpath_orig); 636 } 637 if (isset($this->description)) { 638 $this->description = trim($this->description); 639 } 640 if (isset($this->keywords)) { 641 $this->keywords = trim($this->keywords); 642 } 643 if (isset($this->cover)) { 644 $this->cover = trim($this->cover); 645 } 646 if (isset($this->gen_or_uploaded)) { 647 $this->gen_or_uploaded = trim($this->gen_or_uploaded); 648 } 649 if (isset($this->extraparams)) { 650 $this->extraparams = trim($this->extraparams); 651 } 652 if (isset($this->fk_user_m)) { 653 $this->fk_user_m = trim($this->fk_user_m); 654 } 655 if (isset($this->acl)) { 656 $this->acl = trim($this->acl); 657 } 658 if (isset($this->src_object_type)) { 659 $this->src_object_type = trim($this->src_object_type); 660 } 661 662 // Check parameters 663 // Put here code to add a control on parameters values 664 665 // Update request 666 $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET'; 667 $sql .= " ref = '".dol_hash($this->filepath.'/'.$this->filename, 3)."',"; 668 $sql .= ' label = '.(isset($this->label) ? "'".$this->db->escape($this->label)."'" : "null").','; 669 $sql .= ' share = '.(!empty($this->share) ? "'".$this->db->escape($this->share)."'" : "null").','; 670 $sql .= ' entity = '.(isset($this->entity) ? $this->entity : $conf->entity).','; 671 $sql .= ' filename = '.(isset($this->filename) ? "'".$this->db->escape($this->filename)."'" : "null").','; 672 $sql .= ' filepath = '.(isset($this->filepath) ? "'".$this->db->escape($this->filepath)."'" : "null").','; 673 $sql .= ' fullpath_orig = '.(isset($this->fullpath_orig) ? "'".$this->db->escape($this->fullpath_orig)."'" : "null").','; 674 $sql .= ' description = '.(isset($this->description) ? "'".$this->db->escape($this->description)."'" : "null").','; 675 $sql .= ' keywords = '.(isset($this->keywords) ? "'".$this->db->escape($this->keywords)."'" : "null").','; 676 $sql .= ' cover = '.(isset($this->cover) ? "'".$this->db->escape($this->cover)."'" : "null").','; 677 $sql .= ' position = '.(isset($this->position) ? $this->db->escape($this->position) : "0").','; 678 $sql .= ' gen_or_uploaded = '.(isset($this->gen_or_uploaded) ? "'".$this->db->escape($this->gen_or_uploaded)."'" : "null").','; 679 $sql .= ' extraparams = '.(isset($this->extraparams) ? "'".$this->db->escape($this->extraparams)."'" : "null").','; 680 $sql .= ' date_c = '.(!isset($this->date_c) || dol_strlen($this->date_c) != 0 ? "'".$this->db->idate($this->date_c)."'" : 'null').','; 681 //$sql .= ' tms = '.(! isset($this->date_m) || dol_strlen($this->date_m) != 0 ? "'".$this->db->idate($this->date_m)."'" : 'null').','; // Field automatically updated 682 $sql .= ' fk_user_m = '.($this->fk_user_m > 0 ? $this->fk_user_m : $user->id).','; 683 $sql .= ' acl = '.(isset($this->acl) ? "'".$this->db->escape($this->acl)."'" : "null").','; 684 $sql .= ' src_object_id = '.($this->src_object_id > 0 ? $this->src_object_id : "null").','; 685 $sql .= ' src_object_type = '.(isset($this->src_object_type) ? "'".$this->db->escape($this->src_object_type)."'" : "null"); 686 $sql .= ' WHERE rowid='.((int) $this->id); 687 688 $this->db->begin(); 689 690 $resql = $this->db->query($sql); 691 if (!$resql) { 692 $error++; 693 $this->errors[] = 'Error '.$this->db->lasterror(); 694 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR); 695 } 696 697 // Triggers 698 if (!$error && !$notrigger) { 699 // Call triggers 700 $result = $this->call_trigger(strtoupper(get_class($this)).'_MODIFY', $user); 701 if ($result < 0) { 702 $error++; 703 } //Do also here what you must do to rollback action if trigger fail 704 // End call triggers 705 } 706 707 // Commit or rollback 708 if ($error) { 709 $this->db->rollback(); 710 711 return -1 * $error; 712 } else { 713 $this->db->commit(); 714 715 return 1; 716 } 717 } 718 719 /** 720 * Delete object in database 721 * 722 * @param User $user User that deletes 723 * @param bool $notrigger false=launch triggers after, true=disable triggers 724 * 725 * @return int <0 if KO, >0 if OK 726 */ 727 public function delete(User $user, $notrigger = false) 728 { 729 dol_syslog(__METHOD__, LOG_DEBUG); 730 731 $error = 0; 732 733 $this->db->begin(); 734 735 // Triggers 736 if (!$notrigger) { 737 // Call triggers 738 $result = $this->call_trigger(strtoupper(get_class($this)).'_DELETE', $user); 739 if ($result < 0) { 740 $error++; 741 } //Do also here what you must do to rollback action if trigger fail 742 // End call triggers 743 } 744 745 // If you need to delete child tables to, you can insert them here 746 747 if (!$error) { 748 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element; 749 $sql .= ' WHERE rowid='.((int) $this->id); 750 751 $resql = $this->db->query($sql); 752 if (!$resql) { 753 $error++; 754 $this->errors[] = 'Error '.$this->db->lasterror(); 755 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR); 756 } 757 } 758 759 // Commit or rollback 760 if ($error) { 761 $this->db->rollback(); 762 763 return -1 * $error; 764 } else { 765 $this->db->commit(); 766 767 return 1; 768 } 769 } 770 771 /** 772 * Load an object from its id and create a new one in database 773 * 774 * @param User $user User making the clone 775 * @param int $fromid Id of object to clone 776 * @return int New id of clone 777 */ 778 public function createFromClone(User $user, $fromid) 779 { 780 dol_syslog(__METHOD__, LOG_DEBUG); 781 782 $error = 0; 783 $object = new Ecmfiles($this->db); 784 785 $this->db->begin(); 786 787 // Load source object 788 $object->fetch($fromid); 789 // Reset object 790 $object->id = 0; 791 792 // Clear fields 793 // ... 794 795 // Create clone 796 $object->context['createfromclone'] = 'createfromclone'; 797 $result = $object->create($user); 798 799 // Other options 800 if ($result < 0) { 801 $error++; 802 $this->errors = $object->errors; 803 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR); 804 } 805 806 unset($object->context['createfromclone']); 807 808 // End 809 if (!$error) { 810 $this->db->commit(); 811 812 return $object->id; 813 } else { 814 $this->db->rollback(); 815 816 return -1; 817 } 818 } 819 820 /** 821 * Return a link to the object card (with optionaly the picto) 822 * 823 * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) 824 * @param string $option On what the link point to 825 * @param int $notooltip 1=Disable tooltip 826 * @param int $maxlen Max length of visible user name 827 * @param string $morecss Add more css on link 828 * @return string String with URL 829 */ 830 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $maxlen = 24, $morecss = '') 831 { 832 global $db, $conf, $langs; 833 global $dolibarr_main_authentication, $dolibarr_main_demo; 834 global $menumanager; 835 836 if (!empty($conf->dol_no_mouse_hover)) { 837 $notooltip = 1; // Force disable tooltips 838 } 839 840 $result = ''; 841 842 $label = '<u>'.$langs->trans("MyModule").'</u>'; 843 $label .= '<br>'; 844 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref; 845 846 $url = DOL_URL_ROOT.'/ecm/'.$this->table_name.'_card.php?id='.$this->id; 847 848 $linkclose = ''; 849 if (empty($notooltip)) { 850 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { 851 $label = $langs->trans("ShowProject"); 852 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; 853 } 854 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; 855 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; 856 } else { 857 $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); 858 } 859 860 $linkstart = '<a href="'.$url.'"'; 861 $linkstart .= $linkclose.'>'; 862 $linkend = '</a>'; 863 864 if ($withpicto) { 865 $result .= ($linkstart.img_object(($notooltip ? '' : $label), 'label', ($notooltip ? '' : 'class="classfortooltip"')).$linkend); 866 if ($withpicto != 2) { 867 $result .= ' '; 868 } 869 } 870 $result .= $linkstart.$this->ref.$linkend; 871 return $result; 872 } 873 874 /** 875 * Retourne le libelle du status d'un user (actif, inactif) 876 * 877 * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto 878 * @return string Label of status 879 */ 880 public function getLibStatut($mode = 0) 881 { 882 return $this->LibStatut($this->status, $mode); 883 } 884 885 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 886 /** 887 * Return the status 888 * 889 * @param int $status Id status 890 * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 5=Long label + Picto 891 * @return string Label of status 892 */ 893 public static function LibStatut($status, $mode = 0) 894 { 895 // phpcs:enable 896 global $langs; 897 return ''; 898 } 899 900 901 /** 902 * Initialise object with example values 903 * Id must be 0 if object instance is a specimen 904 * 905 * @return void 906 */ 907 public function initAsSpecimen() 908 { 909 global $conf, $user; 910 911 $this->id = 0; 912 $this->specimen = 1; 913 $this->label = '0a1b2c3e4f59999999'; 914 $this->entity = 1; 915 $this->filename = 'myspecimenfilefile.pdf'; 916 $this->filepath = '/aaa/bbb'; 917 $this->fullpath_orig = 'c:/file on my disk.pdf'; 918 $this->description = 'This is a long description of file'; 919 $this->keywords = 'key1,key2'; 920 $this->cover = '1'; 921 $this->position = 5; 922 $this->gen_or_uploaded = 'uploaded'; 923 $this->extraparams = ''; 924 $this->date_c = (dol_now() - 3600 * 24 * 10); 925 $this->date_m = ''; 926 $this->fk_user_c = $user->id; 927 $this->fk_user_m = ''; 928 $this->acl = ''; 929 $this->src_object_type = 'product'; 930 $this->src_object_id = 1; 931 } 932} 933 934 935/** 936 * Class of an index line of a document 937 */ 938class EcmfilesLine 939{ 940 /** 941 * @var string ECM files line label 942 */ 943 public $label; 944 945 /** 946 * @var int Entity 947 */ 948 public $entity; 949 950 public $filename; 951 public $filepath; 952 public $fullpath_orig; 953 954 /** 955 * @var string description 956 */ 957 public $description; 958 959 public $keywords; 960 public $cover; 961 public $position; 962 public $gen_or_uploaded; // can be 'generated', 'uploaded', 'unknown' 963 public $extraparams; 964 public $date_c = ''; 965 public $date_m = ''; 966 967 /** 968 * @var int ID 969 */ 970 public $fk_user_c; 971 972 /** 973 * @var int ID 974 */ 975 public $fk_user_m; 976 977 public $acl; 978 public $src_object_type; 979 public $src_object_id; 980} 981