* * Get related documents for document browser */ if (!defined('NOTOKENRENEWAL')) { define('NOTOKENRENEWAL', '1'); } if (!defined('NOREQUIREMENU')) { define('NOREQUIREMENU', '1'); } if (!defined('NOREQUIREAJAX')) { define('NOREQUIREAJAX', '1'); } // Load Dolibarr environment $res = 0; // Path from /custom/filearchiv/ajax/ to main.inc.php if (!$res && file_exists("../../../main.inc.php")) { $res = @include "../../../main.inc.php"; } // Fallback for different directory structures if (!$res && file_exists("../../../../main.inc.php")) { $res = @include "../../../../main.inc.php"; } if (!$res && file_exists("../../main.inc.php")) { $res = @include "../../main.inc.php"; } if (!$res) { die("Include of main fails"); } require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; // Debug logging $debugFile = '/tmp/filearchiv_getdocs_debug.log'; @file_put_contents($debugFile, date('Y-m-d H:i:s') . " === getdocuments.php called ===\n", FILE_APPEND); // Security check if (!isModEnabled('filearchiv')) { http_response_code(403); echo json_encode(array('success' => false, 'error' => 'Module not enabled')); exit; } $element = GETPOST('element', 'aZ09'); $id = GETPOST('id', 'int'); if (empty($element) || empty($id)) { echo json_encode(array('success' => false, 'error' => 'Missing parameters')); exit; } $langs->load('filearchiv@filearchiv'); // Get the main object $object = null; $thirdparty = null; switch ($element) { case 'propal': require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; $object = new Propal($db); $object->fetch($id); $object->fetch_thirdparty(); $thirdparty = $object->thirdparty; break; case 'commande': require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; $object = new Commande($db); $object->fetch($id); $object->fetch_thirdparty(); $thirdparty = $object->thirdparty; break; case 'facture': require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $object = new Facture($db); $object->fetch($id); $object->fetch_thirdparty(); $thirdparty = $object->thirdparty; break; case 'expedition': require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php'; $object = new Expedition($db); $object->fetch($id); $object->fetch_thirdparty(); $thirdparty = $object->thirdparty; break; case 'order_supplier': require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; $object = new CommandeFournisseur($db); $object->fetch($id); $object->fetch_thirdparty(); $thirdparty = $object->thirdparty; break; case 'invoice_supplier': require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; $object = new FactureFournisseur($db); $object->fetch($id); $object->fetch_thirdparty(); $thirdparty = $object->thirdparty; break; default: echo json_encode(array('success' => false, 'error' => 'Unknown element type')); exit; } if (!$object || !$object->id) { echo json_encode(array('success' => false, 'error' => 'Object not found')); exit; } @file_put_contents($debugFile, "Element: $element, ID: $id\n", FILE_APPEND); @file_put_contents($debugFile, "Object ref: " . $object->ref . ", entity: " . $object->entity . "\n", FILE_APPEND); @file_put_contents($debugFile, "Thirdparty: " . ($thirdparty ? $thirdparty->id . " - " . $thirdparty->name : "none") . "\n", FILE_APPEND); $categories = array(); // 1. Customer/Supplier documents if ($thirdparty && $thirdparty->id) { $socdir = $conf->societe->multidir_output[$thirdparty->entity] . '/' . dol_sanitizeFileName($thirdparty->id); @file_put_contents($debugFile, "Societe dir: $socdir (exists: " . (is_dir($socdir) ? "yes" : "no") . ")\n", FILE_APPEND); $files = getDocumentsForPath($socdir, $debugFile); if (!empty($files)) { $categories[] = array( 'title' => $langs->trans('CustomerDocuments'), 'icon' => 'fa-building', 'files' => $files ); } } // 2. Current object documents $objdir = ''; switch ($element) { case 'propal': $objdir = $conf->propal->multidir_output[$object->entity] . '/' . dol_sanitizeFileName($object->ref); break; case 'commande': $objdir = $conf->commande->multidir_output[$object->entity] . '/' . dol_sanitizeFileName($object->ref); break; case 'facture': $objdir = $conf->facture->multidir_output[$object->entity] . '/' . dol_sanitizeFileName($object->ref); break; case 'expedition': $objdir = $conf->expedition->dir_output . '/sending/' . dol_sanitizeFileName($object->ref); break; case 'order_supplier': $objdir = $conf->fournisseur->commande->multidir_output[$object->entity] . '/' . dol_sanitizeFileName($object->ref); break; case 'invoice_supplier': $objdir = $conf->fournisseur->facture->multidir_output[$object->entity] . '/' . get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier') . dol_sanitizeFileName($object->ref); break; } if ($objdir) { @file_put_contents($debugFile, "Object dir: $objdir (exists: " . (is_dir($objdir) ? "yes" : "no") . ")\n", FILE_APPEND); $files = getDocumentsForPath($objdir, $debugFile); @file_put_contents($debugFile, "Files found: " . count($files) . "\n", FILE_APPEND); if (!empty($files)) { $titleKey = ucfirst($element) . 'Documents'; $categories[] = array( 'title' => $langs->trans($titleKey), 'icon' => getIconForElement($element), 'files' => $files ); } } // 3. Product documents from object lines $productFiles = array(); @file_put_contents($debugFile, "Lines count: " . (isset($object->lines) ? count($object->lines) : "not set") . "\n", FILE_APPEND); if (!empty($object->lines)) { foreach ($object->lines as $line) { if (!empty($line->fk_product) && $line->fk_product > 0) { $proddir = $conf->product->multidir_output[$conf->entity] . '/' . dol_sanitizeFileName($line->fk_product); @file_put_contents($debugFile, "Product dir: $proddir\n", FILE_APPEND); $files = getDocumentsForPath($proddir, $debugFile); foreach ($files as $file) { $file['product_ref'] = $line->ref; $file['product_label'] = $line->product_label; $productFiles[] = $file; } } } } if (!empty($productFiles)) { $categories[] = array( 'title' => $langs->trans('ProductDocuments'), 'icon' => 'fa-cube', 'files' => $productFiles ); } header('Content-Type: application/json; charset=UTF-8'); echo json_encode(array('success' => true, 'categories' => $categories)); /** * Get documents from a directory path * * @param string $path Directory path * @param string $debugFile Debug file path (optional) * @return array Array of file info */ function getDocumentsForPath($path, $debugFile = null) { global $langs; $files = array(); if (!is_dir($path)) { if ($debugFile) { @file_put_contents($debugFile, " Path not a dir: $path\n", FILE_APPEND); } return $files; } if ($debugFile) { @file_put_contents($debugFile, " Scanning dir: $path\n", FILE_APPEND); } $filearray = dol_dir_list($path, 'files', 0, '', '(\.meta|_preview.*\.png)$'); foreach ($filearray as $file) { $files[] = array( 'name' => $file['name'], 'fullpath' => $file['fullname'], 'relativepath' => $file['relativename'], 'size' => $file['size'], 'size_formatted' => dol_print_size($file['size']), 'date' => dol_print_date($file['date'], 'day'), 'icon' => getIconForFile($file['name']) ); } return $files; } /** * Get Font Awesome icon for file type * * @param string $filename Filename * @return string Icon class */ function getIconForFile($filename) { $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); $icons = array( 'pdf' => 'fa-file-pdf', 'doc' => 'fa-file-word', 'docx' => 'fa-file-word', 'xls' => 'fa-file-excel', 'xlsx' => 'fa-file-excel', 'ppt' => 'fa-file-powerpoint', 'pptx' => 'fa-file-powerpoint', 'jpg' => 'fa-file-image', 'jpeg' => 'fa-file-image', 'png' => 'fa-file-image', 'gif' => 'fa-file-image', 'zip' => 'fa-file-archive', 'rar' => 'fa-file-archive', 'txt' => 'fa-file-alt', 'csv' => 'fa-file-csv', ); return isset($icons[$ext]) ? $icons[$ext] : 'fa-file'; } /** * Get icon for element type * * @param string $element Element type * @return string Icon class */ function getIconForElement($element) { $icons = array( 'propal' => 'fa-file-signature', 'commande' => 'fa-file-invoice', 'facture' => 'fa-file-invoice-dollar', 'expedition' => 'fa-truck', 'order_supplier' => 'fa-shopping-cart', 'invoice_supplier' => 'fa-file-invoice', ); return isset($icons[$element]) ? $icons[$element] : 'fa-file'; }