';
echo '
'; // col-10
echo '
'; // row
// Collapsed by default: ONLY render children if folder is on active path
if ($subfolder_count > 0 && ($folders_expanded || $on_active_path)) {
echo '
';
displayFolders($folder_id, $client_id, $indent + 1);
echo ' ';
}
echo '';
}
}
// ---------------------------------------------
// DATA LOAD
// view=1 (grid) - every file in the folder, thumbnail or file-type icon
// view=0 (list) loads ALL files+documents, merges, sorts in PHP
// ---------------------------------------------
$items = [];
$num_rows = [0];
// Both views decide previewability from this, so it is set before the branch -
// it used to be assigned inside the grid arm only, which left the list arm
// passing null to in_array()
$inline_viewable_mime_types = getInlineViewableMimeTypes();
if ($view == 1) {
/*
* GRID VIEW: files AND documents, same as the list view beside it.
*
* This used to be a single files-only query with SQL_CALC_FOUND_ROWS and a
* LIMIT. Two sources cannot be paginated by one LIMIT, so it now mirrors
* exactly what the list view does: fetch both unpaginated, merge, sort by
* name, and slice in PHP. That also fixes the grid quietly omitting every
* created document - they were only ever visible in list view.
*/
$safe_q = mysqli_real_escape_string($mysqli, $q);
if ($get_folder_id == 0 && isset($_GET["q"])) {
$file_folder_snippet = ""; // search across all folders
$doc_folder_snippet = "";
} else {
$file_folder_snippet = "AND file_folder_id = $folder_id";
$doc_folder_snippet = "AND document_folder_id = $folder_id";
}
$file_search_snippet = "";
$doc_search_snippet = "";
if (!empty($q)) {
$file_search_snippet = "AND (file_name LIKE '%$safe_q%' OR file_ext LIKE '%$safe_q%' OR file_description LIKE '%$safe_q%')";
$doc_search_snippet = "AND (MATCH(document_content_raw) AGAINST ('$safe_q') OR document_name LIKE '%$safe_q%')";
}
// Skipped outright when the type filter excludes them
$sql_grid_files = false;
if ($type_filter !== 'document') {
$sql_grid_files = mysqli_query(
$mysqli,
"SELECT files.*, users.user_name
FROM files
LEFT JOIN users ON file_created_by = user_id
WHERE file_client_id = $client_id
AND file_$archive_query
$file_folder_snippet
$file_search_snippet"
);
}
$sql_grid_documents = false;
if ($type_filter !== 'file') {
$sql_grid_documents = mysqli_query(
$mysqli,
"SELECT documents.*, users.user_name
FROM documents
LEFT JOIN users ON document_created_by = user_id
WHERE document_client_id = $client_id
AND document_$archive_query
$doc_folder_snippet
$doc_search_snippet"
);
}
while ($sql_grid_files && ($row = mysqli_fetch_assoc($sql_grid_files))) {
$row['grid_kind'] = 'file';
$items[] = $row;
}
while ($sql_grid_documents && ($row = mysqli_fetch_assoc($sql_grid_documents))) {
$row['grid_kind'] = 'document';
$items[] = $row;
}
usort($items, function ($a, $b) {
$a_name = strtolower($a['grid_kind'] === 'file' ? $a['file_name'] : $a['document_name']);
$b_name = strtolower($b['grid_kind'] === 'file' ? $b['file_name'] : $b['document_name']);
return strcmp($a_name, $b_name);
});
$num_rows = [count($items)];
$items = array_slice($items, $record_from, $record_to);
} else {
// -------- LIST VIEW: build unified items[] --------
// Folder filter
if ($get_folder_id == 0 && isset($_GET["q"])) {
$file_folder_snippet = ""; // search across all folders
$doc_folder_snippet = "";
} else {
$file_folder_snippet = "AND file_folder_id = $folder_id";
$doc_folder_snippet = "AND document_folder_id = $folder_id";
}
// Search filters
$safe_q = mysqli_real_escape_string($mysqli, $q);
$file_search_snippet = "";
if (!empty($q)) {
$file_search_snippet = "AND (file_name LIKE '%$safe_q%' OR file_ext LIKE '%$safe_q%' OR file_description LIKE '%$safe_q%')";
}
$doc_search_snippet = "";
if (!empty($q)) {
$doc_search_snippet = "AND (MATCH(document_content_raw) AGAINST ('$safe_q') OR document_name LIKE '%$safe_q%')";
}
// Files query (NO limit - we'll paginate in PHP). Skipped outright when the
// type filter excludes files, rather than fetching rows to throw away.
$sql_files = false;
if ($type_filter !== 'document') {
$sql_files = mysqli_query(
$mysqli,
"SELECT files.*, users.user_name
FROM files
LEFT JOIN users ON file_created_by = user_id
WHERE file_client_id = $client_id
AND file_$archive_query
$file_folder_snippet
$file_search_snippet"
);
}
// Documents query (NO limit - paginate in PHP)
$sql_documents = false;
if ($type_filter !== 'file') {
$sql_documents = mysqli_query(
$mysqli,
"SELECT documents.*, users.user_name
FROM documents
LEFT JOIN users ON document_created_by = user_id
WHERE document_client_id = $client_id
AND document_$archive_query
$doc_folder_snippet
$doc_search_snippet"
);
}
// Normalize FILES into $items
while ($sql_files && ($row = mysqli_fetch_assoc($sql_files))) {
$file_id = intval($row['file_id']);
$file_name = escapeHtml($row['file_name']);
$file_description = escapeHtml($row['file_description']);
$file_reference_name= escapeHtml($row['file_reference_name']);
$file_ext = escapeHtml($row['file_ext']);
$file_size = intval($row['file_size']);
$file_mime_type = escapeHtml($row['file_mime_type']);
$file_uploaded_by = escapeHtml($row['user_name']);
$file_created_at = escapeHtml($row['file_created_at']);
$file_archived_at = $row['file_archived_at'];
// determine icon
if ($file_ext == 'pdf') {
$file_icon = "file-pdf";
} elseif (in_array($file_ext, ['gz','tar','zip','7z','rar'])) {
$file_icon = "file-archive";
} elseif (in_array($file_ext, ['txt','md'])) {
$file_icon = "file-alt";
} elseif ($file_ext == 'msg') {
$file_icon = "envelope";
} elseif (in_array($file_ext, ['doc','docx','odt'])) {
$file_icon = "file-word";
} elseif (in_array($file_ext, ['xls','xlsx','ods'])) {
$file_icon = "file-excel";
} elseif (in_array($file_ext, ['pptx','odp'])) {
$file_icon = "file-powerpoint";
} elseif (in_array($file_ext, ['mp3','wav','ogg'])) {
$file_icon = "file-audio";
} elseif (in_array($file_ext, ['mov','mp4','av1'])) {
$file_icon = "file-video";
} elseif (in_array($file_ext, ['jpg','jpeg','png','gif','webp','bmp','tif'])) {
$file_icon = "file-image";
} else {
$file_icon = "file";
}
$items[] = [
'kind' => 'file',
'id' => $file_id,
'name' => $file_name,
'description' => $file_description,
'reference_name' => $file_reference_name,
'icon' => $file_icon,
'ext' => $file_ext,
'mime' => $file_mime_type,
'size' => $file_size,
'created_at' => $file_created_at,
'created_by' => $file_uploaded_by,
'archived_at' => $file_archived_at,
];
}
// Normalize DOCUMENTS into $items
while ($sql_documents && ($row = mysqli_fetch_assoc($sql_documents))) {
$document_id = intval($row['document_id']);
$document_name = escapeHtml($row['document_name']);
$document_description = escapeHtml($row['document_description']);
$document_created_by_name = escapeHtml($row['user_name']);
$document_created_at = $row['document_created_at'];
$document_updated_at = $row['document_updated_at'];
$document_archived_at = $row['document_archived_at'];
$items[] = [
'kind' => 'document',
'id' => $document_id,
'name' => $document_name,
'description' => $document_description,
'mime' => 'Document',
'size' => null,
'updated_at' => $document_updated_at,
'created_by' => $document_created_by_name,
'archived_at' => $document_archived_at,
];
}
// Sort combined items
$sort = isset($_GET['sort']) ? $_GET['sort'] : 'name';
$order = isset($_GET['order']) ? $_GET['order'] : 'ASC';
usort($items, function($a, $b) use ($sort, $order) {
$direction = ($order === 'DESC') ? -1 : 1;
if ($sort == 'created') {
$valA = strtotime($a['created_at']);
$valB = strtotime($b['created_at']);
} elseif ($sort == 'type') {
$valA = strtolower($a['mime']);
$valB = strtolower($b['mime']);
} elseif ($sort == 'size') {
$valA = (int)($a['size'] ?? 0);
$valB = (int)($b['size'] ?? 0);
} else {
// default: name
$valA = strtolower($a['name']);
$valB = strtolower($b['name']);
}
if ($valA == $valB) {
return 0;
}
return ($valA < $valB) ? -1 * $direction : 1 * $direction;
});
// Total items (for pagination footer)
$total_items = count($items);
$num_rows = [$total_items];
// Apply pagination slice
$items = array_slice($items, $record_from, $record_to);
}
// ---------------------------------------------
// Root folder count (for "/" badge)
// ---------------------------------------------
$row_root_files = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('file_id') AS num FROM files WHERE file_folder_id = 0 AND file_client_id = $client_id AND file_$archive_query"));
$row_root_docs = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('document_id') AS num FROM documents WHERE document_folder_id = 0 AND document_client_id = $client_id AND document_$archive_query"));
$num_root_items = intval($row_root_files['num']) + intval($row_root_docs['num']);
?>
Root
= $bread_crumb_folder_name ?>
No files in this folder.
No documents in this folder.
Nothing in this folder.
$file_id,
'name' => $file_name,
'kind' => $file_preview_kind,
'icon' => $file_icon,
'ext' => strtoupper($file_ext),
'size' => $file_size_human,
'excerpt' => $file_excerpt,
'preview' => $file_open_url,
'download' => $file_download_url,
'action' => ($item_kind === 'document') ? 'Open full page' : 'Download'
];
?>