- <?php
-
- // Configuration
- $apiToken = ""; // API Token (menu->options, ETAPI)
- $serverUrl = "http://127.0.0.1:8181"; // location to your trilium instance
- $parentNoteId = ""; // Change this to the parent note ID you want to list sub-notes for (The main folder/note)
- $localFolder = '/NAS/Docs/trilium-data/'; // folder to sync to
-
- // leave below here
- $deletedFolders = array();
- $deletedFiles = array();
-
- function getTriliumVersion($apiToken, $serverUrl) {
- $url = "$serverUrl/etapi/app-info";
-
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HTTPHEADER, [
- "Authorization: $apiToken",
- "Content-Type: application/json"
- ]);
-
- $response = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
-
- if ($httpCode !== 200) {
- die("Error fetching notes: HTTP $httpCode\n$response");
- }
-
- return json_decode($response, true);
- }
-
- function checkFolderAccess($folderPath) {
- if (!is_dir($folderPath) || !is_readable($folderPath)) {
- die("Error: Cannot access folder '$folderPath'.");
- }
- }
-
- function fetchSubNotes($parentNoteId, $apiToken, $serverUrl) {
- $url = "$serverUrl/etapi/notes/$parentNoteId";
-
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HTTPHEADER, [
- "Authorization: $apiToken",
- "Content-Type: application/json"
- ]);
-
- $response = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
-
- if ($httpCode !== 200) {
- die("Error fetching notes: HTTP $httpCode\n$response");
- }
-
- return json_decode($response, true);
- }
-
- function fetchNoteContents($noteId, $apiToken, $serverUrl) {
- $url = "$serverUrl/etapi/notes/$noteId/content";
-
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HTTPHEADER, [
- "Authorization: $apiToken",
- "Content-Type: application/json"
- ]);
-
- $response = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
-
- if ($httpCode !== 200) {
- return "Error fetching notes: HTTP $httpCode\n$response";
- }
-
- $response = convertHtmlToText($response);
-
- return $response;
- }
-
- function updateNoteContents($noteId, $content, $apiToken, $serverUrl) {
- $url = "$serverUrl/etapi/notes/$noteId/content";
-
- $html = convertTextToHtml($content);
-
- // Initialise cURL request
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); // Set the request method to PUT
- curl_setopt($ch, CURLOPT_HTTPHEADER, [
- "Authorization: $apiToken",
- "Content-Type: text/plain"
- ]);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $html); // Add formatted HTML to the body
-
- $response = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
-
- if ($httpCode !== 204) {
- die("Error updating note: HTTP $httpCode\n$response");
- }
-
- return;
- }
-
- function createNote($parentNoteId, $title, $content, $apiToken, $serverUrl) {
- $url = "$serverUrl/etapi/create-note";
-
- $data = json_encode([
- "parentNoteId" => $parentNoteId,
- "title" => $title,
- "type" => "text",
- "content" => $content
- ]);
-
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HTTPHEADER, [
- "Authorization: $apiToken",
- "Content-Type: application/json"
- ]);
- curl_setopt($ch, CURLOPT_POST, true);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
-
- $response = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
-
- $response = json_decode($response, true);
- return $response['note'];
- }
-
- function deleteNote($noteId, $apiToken, $serverUrl){
- $url = "$serverUrl/etapi/notes/$noteId";
-
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HTTPHEADER, [
- "Authorization: $apiToken",
- "Content-Type: application/json"
- ]);
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
-
- $response = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
-
- if ($httpCode === 204) {
- return true; // Deletion successful
- }
-
- return json_decode($response, true); // Return JSON response for errors
- }
-
- function fetchAllNotes($noteId, $apiToken, $serverUrl, $localFolder, $path = '') {
- $note = fetchSubNotes($noteId, $apiToken, $serverUrl);
-
- if (!empty($note['childNoteIds'])) {
- $currentPath = $path . $note['title'] . '/';
-
- $fullPath = rtrim($localFolder, '/') . '/' . ltrim($path, '/') . '/' . ltrim($note['title'], '/');
- $fullPath = preg_replace('/\/+/', '/', $fullPath);
-
- if (is_dir($fullPath)) {
- $status = 'Exists';
- $modifiedDisk = stat($fullPath)['mtime'];
- } else {
- $status = 'Missing_Disk';
- $modifiedDisk = "";
- }
-
- $folder = [
- 'noteId' => $noteId,
- 'folder' => $note['title'],
- 'dateModifiedTrilium' => convertToUnixTimestamp($note['dateModified']),
- 'dateModifiedDisk' => $modifiedDisk,
- 'parent' => $note['parentNoteIds'][0],
- 'children' => [],
- 'status' => $status
- ];
-
- foreach ($note['childNoteIds'] as $childId) {
- $folder['children'][] = fetchAllNotes($childId, $apiToken, $serverUrl, $localFolder, $currentPath);
- }
-
- return $folder;
- } else {
-
- $fullPath = $localFolder . $path . $note['title'];
- //echo "does it exist?: $fullPath\n";
- $fileExists = file_exists($fullPath) ? 'Exists' : 'Missing_Disk';
-
- if ($fileExists === 'Exists' && is_file($fullPath)) {
- $modifiedDisk = convertToUnixTimestamp(filemtime($fullPath));
- $hashDisk = md5(file_get_contents($fullPath));
- } else {
- $modifiedDisk = "";
- $hashDisk = "";
- }
-
- $hashTrilium = md5(fetchNoteContents($noteId, $apiToken, $serverUrl));
-
- return [
- 'noteId' => $noteId,
- 'file' => $note['title'],
- 'path' => $fullPath,
- 'dateModifiedTrilium' => convertToUnixTimestamp($note['dateModified']),
- 'dateModifiedDisk' => $modifiedDisk,
- 'parent' => $note['parentNoteIds'][0],
- 'hashTrilium' => $hashTrilium,
- 'hashDisk' => $hashDisk,
- 'hashMach' => "",
- 'status' => $fileExists
- ];
- }
- }
-
- function scanLocalFiles($directory, $basePath, $path = '') {
- $files = [];
- $items = scandir($directory);
-
- foreach ($items as $item) {
- if ($item === '.' || $item === '..') continue;
-
- $fullPath = rtrim($directory, '/') . '/' . $item;
- $relativePath = str_replace($basePath, '', $fullPath);
- $currentPath = rtrim($path, '/') . '/' . $item;
-
- if (is_dir($fullPath)) {
- $modifiedDisk = stat($fullPath)['mtime'];
- $files[] = [
- 'noteId' => "",
- 'folder' => $item,
- 'dateModifiedTrilium' => "",
- 'dateModifiedDisk' => $modifiedDisk,
- 'children' => scanLocalFiles($fullPath, $basePath, $currentPath), // Recursive call for directories
- 'parent' => "",
- 'status' => 'Missing_Trilium',
- ];
- } else {
- $hashDisk = md5(file_get_contents($fullPath));
- $files[] = [
- 'noteId' => "",
- 'file' => $item,
- 'dateModifiedTrilium' => "",
- 'dateModifiedDisk' => convertToUnixTimestamp(filemtime($fullPath)),
- 'status' => 'Missing_Trilium',
- 'parent' => "",
- 'hashTrilium' => '',
- 'hashDisk' => $hashDisk,
- 'hashMach' => "",
- 'path' => ltrim($relativePath, '/'),
- ];
- }
- }
-
- return $files;
- }
-
- function mergeStructures(&$triliumStructure, $localFiles) {
- $triliumPaths = [];
-
- if (isset($triliumStructure['children'])) {
- foreach ($triliumStructure['children'] as &$child) {
- $key = isset($child['folder']) ? $child['folder'] : $child['file'];
- $triliumPaths[$key] = &$child;
- }
- } else {
- $triliumStructure['children'] = [];
- }
-
- foreach ($localFiles as $localItem) {
- $key = isset($localItem['folder']) ? $localItem['folder'] : $localItem['file'];
-
- if (!isset($triliumPaths[$key])) {
- if (isset($localItem['path'])) {
- $localItem['path'] = preg_replace('|^[^/]+/|', '', $localItem['path']);
- }
- $triliumStructure['children'][] = $localItem;
- } else if (isset($localItem['children'])) {
- mergeStructures($triliumPaths[$key], $localItem['children']);
- }
- }
- }
-
- function compareFileHashes(&$item) {
- // If the item is an array, check if it has children
- if (isset($item['children']) && is_array($item['children'])) {
- foreach ($item['children'] as &$child) {
- compareFileHashes($child);
- }
- }
-
- // Perform hash comparison only if it's a leaf node (has 'file' but no 'children')
- if (isset($item['file']) && (!isset($item['children']) || empty($item['children']))) {
- if (!empty($item['hashTrilium']) && !empty($item['hashDisk'])) {
- if ($item['hashTrilium'] === $item['hashDisk']) {
- $item['hashMatch'] = "Match";
- } else {
- $item['hashMatch'] = 'Diff';
- if($item['dateModifiedTrilium'] < $item['dateModifiedDisk']){ $item['status'] ="Update_Trilium"; }
- if($item['dateModifiedTrilium'] > $item['dateModifiedDisk']){ $item['status'] ="Update_Disk"; }
- }
- } else {
- $item['hashMatch'] = 'N/A';
- }
-
- }
- }
-
- function createTriliumFolder(&$item, $path = '',$parentNoteId = null) {
- global $localFolder, $apiToken, $serverUrl;
- global $deletedFolders, $deletedFiles;
- // Assign the parent's noteId as the parentId for the current item
-
- if (isset($item['folder']) && strpos($item['folder'], '[del]') !== 0 ) {
-
- $startsWithDeleted = false;
- foreach ($deletedFolders as $deletedFolder) {
- if (strncmp($path . $item['folder'] ."/", $deletedFolder, strlen($deletedFolder)) === 0) {
- $startsWithDeleted = true;
- break;
- }
- }
-
- if (!empty($item['status']) && $item['status'] == "Missing_Trilium" ) {
- if(!$startsWithDeleted){
- $fullpath = $path . $item['folder'] . '/';
- echo "[+] creating trilium folder: $fullpath\n";
-
- $newId = createNote($parentNoteId, $item['folder'], "", $apiToken, $serverUrl);
- // Update item with new noteId
- $item['noteId'] = $newId['noteId'];
- $item['dateModifiedTrilium'] = time();
- $item['status'] = "Updated";
- } else{
- $item['status'] = "Skipped";
- }
- }
- }
-
- // Update parentId for immediate children
- if (isset($item['children']) && is_array($item['children'])) {
- foreach ($item['children'] as &$child) {
- if (isset($item['noteId']) && !empty($item['noteId'])) {
- $child['parent'] = $item['noteId'];
- }
- $currentPath = $path . $item['folder'] . '/';
- createTriliumFolder($child, $currentPath, $item['noteId']);
- }
- }
- }
-
- function createTriliumFile(&$item, $path = '',$parentNoteId = null) {
- global $localFolder, $apiToken, $serverUrl;
- global $deletedFolders, $deletedFiles;
-
- if (isset($item['file']) && strpos($item['file'], '[del]') !== 0) {
-
- $startsWithDeleted = false;
- foreach ($deletedFolders as $deletedFolder) {
- if (strncmp($path , $deletedFolder, strlen($deletedFolder)) === 0) {
- $startsWithDeleted = true;
- break;
- }
- }
- foreach ($deletedFiles as $deletedFile) {
- if (strncmp($path . $item['file'] , $deletedFile, strlen($deletedFile)) === 0) {
- $startsWithDeleted = true;
- break;
- }
- }
-
- if (!empty($item['status']) && $item['status'] == "Missing_Trilium") {
- if(!$startsWithDeleted){
- $fullpath = $localFolder . $path . $item['file'] ;
- echo "[+] creating trilium note: $fullpath\n";
-
- $contents = file_get_contents($fullpath);
- $newId = createNote($parentNoteId, $item['file'], $contents, $apiToken, $serverUrl);
- // Update item with new noteId
- $item['noteId'] = $newId['noteId'];
- $item['dateModifiedTrilium'] = time();
- $item['status'] = "Updated";
- }else{ $item['status'] = "Skipped"; }
- }
- }
-
- // Update parentId for immediate children
- if (isset($item['children']) && is_array($item['children'])) {
- foreach ($item['children'] as &$child) {
- if (isset($item['noteId']) && !empty($item['noteId'])) {
- $child['parent'] = $item['noteId'];
- }
- $currentPath = $path . $item['folder'] . '/';
- createTriliumFile($child, $currentPath, $item['noteId']);
- }
- }
- }
-
- function createDiskFileAndFolder(&$item, $path = '', $parentNoteId = null) {
- global $localFolder, $apiToken, $serverUrl;
- global $deletedFolders, $deletedFiles;
-
- // Assign the parent's noteId as the parentId for the current item
- if (isset($item['folder']) && strpos($item['folder'], '[del]') !== 0) {
- if (!empty($item['status']) && $item['status'] == "Missing_Disk") {
- $fullpath = $localFolder . $path . $item['folder'] . '/';
- echo "[+] creating disk folder: $fullpath\n";
-
- mkdir($fullpath, 0777, true);
- $item['dateModifiedDisk'] = time();
- $item['status'] = "Updated";
- }
- }
-
- if (isset($item['file']) && strpos($item['file'], '[del]') !== 0) {
-
- $startsWithDeleted = false;
- foreach ($deletedFolders as $deletedFolder) {
- if (strncmp($path , $deletedFolder, strlen($deletedFolder)) === 0) {
- $startsWithDeleted = true;
- break;
- }
- }
- foreach ($deletedFiles as $deletedFile) {
- if (strncmp($path . $item['file'] , $deletedFile, strlen($deletedFile)) === 0) {
- $startsWithDeleted = true;
- break;
- }
- }
-
- if (!empty($item['status']) && $item['status'] == "Missing_Disk") {
- if(!$startsWithDeleted){
- $fullpath = $localFolder . $path . $item['file'] ;
- echo "[+] creating disk note: $fullpath\n";
-
- file_put_contents($fullpath, fetchNoteContents($item['noteId'], $apiToken, $serverUrl) );
- $item['dateModifiedDisk'] = time();
- $item['status'] = "Updated";
- }else{ $item['status'] = "Skipped"; }
- }
- }
-
- // Update parentId for immediate children
- if (isset($item['children']) && is_array($item['children'])) {
- foreach ($item['children'] as &$child) {
- if (isset($item['noteId']) && !empty($item['noteId'])) {
- $child['parent'] = $item['noteId'];
- }
- $currentPath = $path . $item['folder'] . '/';
- createDiskFileAndFolder($child, $currentPath, $item['noteId']);
- }
- }
- }
-
- function deleteItem(&$item, $path = '', $parentNoteId = null) {
- global $localFolder, $apiToken, $serverUrl;
- global $deletedFolders, $deletedFiles;
- // Assign the parent's noteId as the parentId for the current item
- if (isset($item['folder']) && strpos($item['folder'], '[del]') === 0) {
- $item['status'] = "Delete";
-
- $item_fixed = trim(substr($item['folder'], 5)); // Remove "[del]" from the start
- $fullpath = $localFolder . $path . $item_fixed . '/';
- echo "[-] deleting disk folder: $fullpath\n";
- $deletedFolders[] = $path . $item_fixed . '/';
- $deletedFolders[] = $path . $item['folder'] . '/';
-
- deleteFolderAndContents($fullpath);
- deleteNote($item['noteId'], $apiToken, $serverUrl);
- }
-
- if (isset($item['file']) && strpos($item['file'], '[del]') === 0) {
- $item['status'] = "Delete";
-
- $item_fixed = trim(substr($item['file'], 5)); // Remove "[del]" from the start
- $fullpath = $localFolder . $path . $item_fixed ;
- echo "[-] deleting disk file: $fullpath\n";
- $deletedFiles[] = $path . $item_fixed;
- $deletedFiles[] = $path . $item['file'];
-
- deleteNote($item['noteId'], $apiToken, $serverUrl);
- if (file_exists($fullpath)) {
- if (is_file($fullpath)) {
- unlink($fullpath);
- } elseif (is_dir($fullpath)) {
- foreach (array_diff(scandir($fullpath), ['.', '..']) as $file) {
- unlink("$fullpath") ?: rmdir("$fullpath");
- }
- rmdir($fullpath);
- }
- }
-
- }
-
- // Update parentId for immediate children
- if (isset($item['children']) && is_array($item['children'])) {
- foreach ($item['children'] as &$child) {
- if (isset($item['folder']) && strpos($item['folder'], '[del]') === 0)
- $child['status'] == "Delete";
- $currentPath = $path . $item['folder'] . '/';
- deleteItem($child, $currentPath, $item['noteId']);
- }
- }
- }
-
- function deleteFolderAndContents($folderPath) {
- if (!is_dir($folderPath)) {
- return false; // Ensure it's a directory
- }
-
- // Scan the directory for all files and subdirectories
- $files = array_diff(scandir($folderPath), array('.', '..'));
-
- foreach ($files as $file) {
- $filePath = $folderPath . DIRECTORY_SEPARATOR . $file;
-
- if (is_dir($filePath)) {
- deleteFolderAndContents($filePath);
- } else {
-
- unlink($filePath);
- }
- }
- return rmdir($folderPath);
- }
-
- function updateExistingFile(&$item, $path = '', $parentNoteId = null){
- global $localFolder, $apiToken, $serverUrl;
-
- if (isset($item['file'])) {
- if (!empty($item['status']) && $item['status'] == "Update_Trilium") {
- $fullpath = $localFolder . $path . $item['file'] ;
- echo "[+] updating file on trilium: $fullpath\n";
-
- $content = file_get_contents($fullpath);
- updateNoteContents($item['noteId'], $content, $apiToken, $serverUrl);
- $item['dateModifiedTrilium'] = time();
- $item['status'] = "Updated";
- }
- }
-
- if (isset($item['file'])) {
- if (!empty($item['status']) && $item['status'] == "Update_Disk") {
- $fullpath = $localFolder . $path . $item['file'] ;
- echo "[+] updating file on disk: $fullpath\n";
-
- file_put_contents($fullpath, fetchNoteContents($item['noteId'], $apiToken, $serverUrl) );
- $item['dateModifiedDisk'] = time();
- $item['status'] = "Updated";
- }
- }
-
- // Update parentId for immediate children
- if (isset($item['children']) && is_array($item['children'])) {
- foreach ($item['children'] as &$child) {
- $currentPath = $path . $item['folder'] . '/';
- updateExistingFile($child, $currentPath, $item['noteId']);
- }
- }
- }
-
- function printFolderTable($structure, $path = '', $printHeader = true) {
- // Define column widths to ensure consistent formatting
- $columnWidths = [
- 'path' => 25,
- 'folder' => 25,
- 'parent' => 13,
- 'noteId' => 13,
- 'dateModifiedTrilium' => 11,
- 'dateModifiedDisk' => 11,
- 'status' => 15
- ];
-
- if ($printHeader) {
- echo "- Folders -\n";
- echo formatColumn("Folder/Path", 25) .
- formatColumn("Folder Name", 25) .
- formatColumn("Parent", 13) .
- formatColumn("noteId", 13) .
- formatColumn("Mod Trl", 11) .
- formatColumn("Mod Dsk", 11) .
- formatColumn("Status", 15) . "\n";
- }
-
- if (isset($structure['folder'])) {
- $currentPath = $path . $structure['folder'] . '/';
-
- // Print the folder details
- echo formatColumn($currentPath, $columnWidths['path']) .
- formatColumn($structure['folder'], $columnWidths['folder']) .
- formatColumn($structure['parent'], $columnWidths['parent']) .
- formatColumn($structure['noteId'], $columnWidths['noteId']) .
- formatColumn($structure['dateModifiedTrilium'], $columnWidths['dateModifiedTrilium']) .
- formatColumn($structure['dateModifiedDisk'], $columnWidths['dateModifiedDisk']) .
- formatColumn($structure['status'], $columnWidths['status']) . "\n";
-
- // Recursively process children
- foreach ($structure['children'] as $child) {
- printFolderTable($child, $currentPath, false);
- }
- }
- }
-
- function printFileTable($structure, $path = '', $printHeader = true) {
- // Define column widths to ensure consistent formatting
- $columnWidths = [
- 'path' => 25,
- 'parent' => 13,
- 'noteId' => 13,
- 'file' => 25,
- 'dateModifiedTrilium' => 11,
- 'dateModifiedDisk' => 11,
- 'hashMatch' => 6,
- 'status' => 15
- ];
-
- if ($printHeader) {
- echo "- Files -\n";
- echo formatColumn("Folder/Path", 25) .
- formatColumn("Filename", 25) .
- formatColumn("Parent", 13) .
- formatColumn("noteId", 13) .
- formatColumn("Mod Trl", 11) .
- formatColumn("Mod Dsk", 11) .
- formatColumn("Hash", 6) .
- formatColumn("Status", 15) . "\n";
- }
-
- if (isset($structure['folder'])) {
- $currentPath = $path . $structure['folder'] . '/';
- foreach ($structure['children'] as $child) {
- printFileTable($child, $currentPath, false);
- }
- } else {
- // Format and print the table row with aligned columns
- echo formatColumn($path, $columnWidths['path']) .
- formatColumn($structure['file'], $columnWidths['file']) .
- formatColumn($structure['parent'], $columnWidths['parent']) .
- formatColumn($structure['noteId'], $columnWidths['noteId']) .
- formatColumn($structure['dateModifiedTrilium'], $columnWidths['dateModifiedTrilium']) .
- formatColumn($structure['dateModifiedDisk'], $columnWidths['dateModifiedDisk']) .
- formatColumn($structure['hashMatch'], $columnWidths['hashMatch']) .
- formatColumn($structure['status'], $columnWidths['status']) . "\n";
- }
- }
-
- function convertToUnixTimestamp($timestamp) {
- // If timestamp is already an integer (Unix timestamp), return it directly
- if (is_int($timestamp)) {
- return $timestamp;
- }
-
- // For other formats, convert to Unix timestamp
- $date = new DateTime($timestamp);
- return $date->getTimestamp();
- }
-
- function convertTextToHtml($text) {
- // 1: Plain Text Search
- $text = str_replace("&", "&", $text);
- $text = str_replace("<", "<", $text);
- $text = str_replace(">", ">", $text);
-
- // 2: Convert Tabs to 4 's
- $text = str_replace("\t", " ", $text);
-
- // 3: Line Breaks
- $text = preg_replace("/\r\n?|\n/", "<br>", $text);
-
- // 4: Paragraphs (Replacing two or more line breaks with paragraph tags)
- $text = preg_replace("/<br>\s*<br>/", "</p><p>", $text);
-
- // 5: Wrap in Paragraph Tags
- $text = "<p>" . $text . "</p>";
-
- return $text;
- }
-
- function convertHtmlToText($html) {
- // Replace <br>, <br/> and <br /> tags with newlines
- $html = str_ireplace(["<br>", "<br/>", "<br />"], "\n", $html);
-
- // Replace <p> and </p> tags with double newlines (to separate paragraphs)
- $html = str_ireplace("</p>", "\n\n", $html);
- $html = str_ireplace("<p>", "", $html); // Remove opening <p> tags
-
- // Convert four into a tab (\t)
- $html = str_ireplace(" ", "\t", $html);
-
- // Replace other common HTML tags (like <div>, <span>, etc.) by stripping them
- $html = strip_tags($html);
-
- // Replace HTML entities like &, <, >, , etc. with their corresponding characters
- $html = html_entity_decode($html, ENT_QUOTES | ENT_HTML5, 'UTF-8');
-
- // Remove excessive spaces and normalise newlines
- $html = preg_replace('/[ ]+/', ' ', $html); // Replace multiple spaces or tabs with a single space
- $html = trim($html); // Remove leading/trailing whitespace
-
- return $html;
- }
-
- function formatColumn($str, $width) {
- // Function to pad the strings to align the columns
- return str_pad($str, $width, ' ', STR_PAD_RIGHT);
- }
-
- echo "[i] checking connections\n";
- $appInfo = getTriliumVersion($apiToken, $serverUrl);
- checkFolderAccess($localFolder);
- echo "[i] version: ".$appInfo['appVersion']."\n";
-
- echo "[i] gathering info\n";
- $structure = fetchAllNotes($parentNoteId, $apiToken, $serverUrl, $localFolder);
- $localFiles = scanLocalFiles($localFolder."Synced/", $localFolder."Synced/");
- mergeStructures($structure, $localFiles);
- compareFileHashes($structure);
-
- // Print the data tables
- printFolderTable($structure);
- printFileTable($structure);
-
- // syncing operations
- deleteItem($structure);
- createTriliumFolder($structure);
- createTriliumFile($structure);
- createDiskFileAndFolder($structure);
- updateExistingFile($structure);
-
- /*
- echo "####### DEBUG ##########\n";
- printFolderTable($structure);
- printFileTable($structure);
- */