db = $db; } /** * Create object in database * * @param User $user User that creates * @return int Return integer <0 if KO, Id of created object if OK */ public function create($user) { global $conf; $error = 0; $now = dol_now(); if (empty($this->fk_anlage) || empty($this->filename) || empty($this->filepath)) { $this->error = 'ErrorMissingParameters'; return -1; } // Determine file type if (empty($this->file_type)) { $this->file_type = $this->determineFileType($this->mimetype, $this->filename); } $this->db->begin(); $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." ("; $sql .= "entity, fk_anlage, filename, filepath, filesize, mimetype,"; $sql .= " file_type, label, description, is_cover, position, share,"; $sql .= " date_creation, fk_user_creat"; $sql .= ") VALUES ("; $sql .= ((int) $conf->entity); $sql .= ", ".((int) $this->fk_anlage); $sql .= ", '".$this->db->escape($this->filename)."'"; $sql .= ", '".$this->db->escape($this->filepath)."'"; $sql .= ", ".((int) $this->filesize); $sql .= ", ".($this->mimetype ? "'".$this->db->escape($this->mimetype)."'" : "NULL"); $sql .= ", '".$this->db->escape($this->file_type)."'"; $sql .= ", ".($this->label ? "'".$this->db->escape($this->label)."'" : "NULL"); $sql .= ", ".($this->description ? "'".$this->db->escape($this->description)."'" : "NULL"); $sql .= ", ".((int) $this->is_cover); $sql .= ", ".((int) $this->position); $sql .= ", ".($this->share ? "'".$this->db->escape($this->share)."'" : "NULL"); $sql .= ", '".$this->db->idate($now)."'"; $sql .= ", ".((int) $user->id); $sql .= ")"; $resql = $this->db->query($sql); if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); } if (!$error) { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element); } if ($error) { $this->db->rollback(); return -1 * $error; } else { $this->db->commit(); return $this->id; } } /** * Load object from database * * @param int $id ID of record * @return int Return integer <0 if KO, 0 if not found, >0 if OK */ public function fetch($id) { global $conf; $sql = "SELECT * FROM ".MAIN_DB_PREFIX.$this->table_element; $sql .= " WHERE rowid = ".((int) $id); $sql .= " AND entity = ".((int) $conf->entity); $resql = $this->db->query($sql); if ($resql) { if ($this->db->num_rows($resql)) { $obj = $this->db->fetch_object($resql); $this->id = $obj->rowid; $this->entity = $obj->entity; $this->fk_anlage = $obj->fk_anlage; $this->filename = $obj->filename; $this->filepath = $obj->filepath; $this->filesize = $obj->filesize; $this->mimetype = $obj->mimetype; $this->file_type = $obj->file_type; $this->label = $obj->label; $this->description = $obj->description; $this->is_cover = $obj->is_cover; $this->position = $obj->position; $this->share = $obj->share; $this->date_creation = $this->db->jdate($obj->date_creation); $this->fk_user_creat = $obj->fk_user_creat; $this->fk_user_modif = $obj->fk_user_modif; $this->db->free($resql); return 1; } else { $this->db->free($resql); return 0; } } else { $this->error = $this->db->lasterror(); return -1; } } /** * Delete object in database and file from disk * * @param User $user User that deletes * @return int Return integer <0 if KO, >0 if OK */ public function delete($user) { global $conf; $error = 0; // Delete physical file (use clean filepath) $fullpath = $this->getFullPath(); if (file_exists($fullpath)) { dol_delete_file($fullpath); // Delete thumbnail if exists $thumbpath = dirname($fullpath).'/thumbs/'.pathinfo($this->filename, PATHINFO_FILENAME).'_small.'.pathinfo($this->filename, PATHINFO_EXTENSION); if (file_exists($thumbpath)) { dol_delete_file($thumbpath); } } $this->db->begin(); $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element." WHERE rowid = ".((int) $this->id); $resql = $this->db->query($sql); if (!$resql) { $error++; $this->errors[] = "Error ".$this->db->lasterror(); } if ($error) { $this->db->rollback(); return -1 * $error; } else { $this->db->commit(); return 1; } } /** * Fetch all files for an installation element * * @param int $anlageId Installation element ID * @param string $fileType Filter by file type (image, pdf, document, other) * @return array Array of AnlageFile objects */ public function fetchAllByAnlage($anlageId, $fileType = '') { global $conf; $results = array(); $sql = "SELECT * FROM ".MAIN_DB_PREFIX.$this->table_element; $sql .= " WHERE fk_anlage = ".((int) $anlageId); $sql .= " AND entity = ".((int) $conf->entity); if ($fileType) { $sql .= " AND file_type = '".$this->db->escape($fileType)."'"; } $sql .= " ORDER BY is_cover DESC, position ASC, filename ASC"; $resql = $this->db->query($sql); if ($resql) { while ($obj = $this->db->fetch_object($resql)) { $file = new AnlageFile($this->db); $file->id = $obj->rowid; $file->fk_anlage = $obj->fk_anlage; $file->filename = $obj->filename; $file->filepath = $obj->filepath; $file->filesize = $obj->filesize; $file->mimetype = $obj->mimetype; $file->file_type = $obj->file_type; $file->label = $obj->label; $file->description = $obj->description; $file->is_cover = $obj->is_cover; $file->position = $obj->position; $file->share = $obj->share; $file->date_creation = $this->db->jdate($obj->date_creation); $results[] = $file; } $this->db->free($resql); } return $results; } /** * Determine file type from mimetype and filename * * @param string $mimetype MIME type * @param string $filename Filename * @return string File type (image, pdf, document, other) */ public function determineFileType($mimetype, $filename) { $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); if (in_array($ext, array('jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp')) || strpos($mimetype, 'image/') === 0) { return 'image'; } if ($ext == 'pdf' || $mimetype == 'application/pdf') { return 'pdf'; } if (in_array($ext, array('doc', 'docx', 'xls', 'xlsx', 'odt', 'ods', 'txt', 'rtf'))) { return 'document'; } return 'other'; } /** * Get full file path * * @return string */ public function getFullPath() { global $conf; return $conf->kundenkarte->dir_output.'/'.$this->getCleanFilepath(); } /** * Get URL to view/download the file * * @param bool $forceDownload If true, force download instead of inline display * @return string */ public function getUrl($forceDownload = false) { // Sanitize filepath - ensure it's relative, not absolute $filepath = $this->getCleanFilepath(); $url = DOL_URL_ROOT.'/document.php?modulepart=kundenkarte&file='.urlencode($filepath); // Add attachment=0 for inline display (especially for PDFs) // If forceDownload is true, don't add this parameter (default Dolibarr behavior is download) if (!$forceDownload) { $url .= '&attachment=0'; } return $url; } /** * Get clean relative filepath (fixes bad data) * * @return string Clean relative filepath */ public function getCleanFilepath() { $filepath = $this->filepath; // If filepath contains "anlagen/" extract from there if (strpos($filepath, 'anlagen/') !== false) { $filepath = substr($filepath, strpos($filepath, 'anlagen/')); } // If it's still an absolute path (starts with / or file:// or Windows drive), just use filename elseif (preg_match('/^(\/|file:\/\/|[A-Za-z]:)/', $filepath)) { // Try to get just the filename and rebuild proper path $filename = basename($filepath); // Use fk_anlage to build correct path if available if ($this->fk_anlage > 0) { global $db; $sql = "SELECT fk_soc FROM ".MAIN_DB_PREFIX."kundenkarte_anlage WHERE rowid = ".((int) $this->fk_anlage); $resql = $db->query($sql); if ($resql && $db->num_rows($resql)) { $obj = $db->fetch_object($resql); $filepath = 'anlagen/'.$obj->fk_soc.'/'.$this->fk_anlage.'/'.$filename; } } } return $filepath; } /** * Get thumbnail URL for images * * @return string */ public function getThumbUrl() { if ($this->file_type != 'image') { return ''; } $filepath = $this->getCleanFilepath(); $dir = dirname($filepath); $filename = pathinfo($this->filename, PATHINFO_FILENAME); $ext = pathinfo($this->filename, PATHINFO_EXTENSION); $thumbpath = $dir.'/thumbs/'.$filename.'_small.'.$ext; // Use attachment=0 for inline display return DOL_URL_ROOT.'/document.php?modulepart=kundenkarte&file='.urlencode($thumbpath).'&attachment=0'; } /** * Set this file as cover image * * @param User $user User making the change * @return int <0 if KO, >0 if OK */ public function setAsCover($user) { $this->db->begin(); // Unset other covers for this anlage $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET is_cover = 0"; $sql .= " WHERE fk_anlage = ".((int) $this->fk_anlage); $this->db->query($sql); // Set this as cover $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET is_cover = 1, fk_user_modif = ".((int) $user->id); $sql .= " WHERE rowid = ".((int) $this->id); $resql = $this->db->query($sql); if ($resql) { $this->is_cover = 1; $this->db->commit(); return 1; } else { $this->db->rollback(); return -1; } } /** * Generate thumbnail for image * * @return bool */ public function generateThumbnail() { global $conf; if ($this->file_type != 'image') { return false; } require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; $fullpath = $this->getFullPath(); if (!file_exists($fullpath)) { return false; } $thumbdir = dirname($fullpath).'/thumbs'; if (!is_dir($thumbdir)) { dol_mkdir($thumbdir); } // Generate small thumbnail $result = vignette($fullpath, 200, 160, '_small', 80, 'thumbs'); return ($result !== false); } }