dbPath = $dbDir . '/indexer.sqlite'; $this->configFile = $indexerFilesDir . '/config.json'; $this->extensionMapFile = $indexerFilesDir . '/local_api/extensionMap.json'; $this->iconsFile = $indexerFilesDir . '/local_api/icons.json'; if (!file_exists($this->dbPath)) { require_once dirname(__FILE__) . '/Initializer.php'; $initializer = new Initializer($indexerFilesDir, $baseDir); $initializer->initializeDatabase(false); } $this->initialize(); } private function initialize() { try { $this->pdo = new PDO('sqlite:' . $this->dbPath); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->createTables(); $this->syncSystemFiles(); } catch (Exception $e) { error_log("Database initialization error: " . $e->getMessage()); throw $e; } } private function createTables() { $this->pdo->exec("CREATE TABLE IF NOT EXISTS system_config ( key TEXT PRIMARY KEY, value TEXT NOT NULL, last_updated INTEGER NOT NULL )"); $this->pdo->exec("CREATE TABLE IF NOT EXISTS extension_mappings ( extension TEXT PRIMARY KEY, indexing_setting TEXT, viewing_setting TEXT, last_updated INTEGER NOT NULL )"); $this->pdo->exec("CREATE TABLE IF NOT EXISTS icon_mappings ( identifier TEXT PRIMARY KEY, icon_filename TEXT NOT NULL, last_updated INTEGER NOT NULL )"); $this->pdo->exec("CREATE TABLE IF NOT EXISTS file_metadata ( path TEXT PRIMARY KEY, filename TEXT NOT NULL, extension TEXT, size INTEGER NOT NULL, modified INTEGER NOT NULL, is_directory INTEGER NOT NULL, parent_path TEXT, indexed_at INTEGER NOT NULL, last_verified INTEGER NOT NULL )"); $this->pdo->exec("CREATE INDEX IF NOT EXISTS idx_file_parent ON file_metadata(parent_path)"); $this->pdo->exec("CREATE INDEX IF NOT EXISTS idx_file_extension ON file_metadata(extension)"); $this->pdo->exec("CREATE INDEX IF NOT EXISTS idx_file_modified ON file_metadata(modified)"); $this->pdo->exec("CREATE INDEX IF NOT EXISTS idx_file_directory ON file_metadata(is_directory)"); } public function syncSystemFiles() { static $synced = false; if ($synced) { return; } $synced = true; if (file_exists($this->configFile)) { $configModified = filemtime($this->configFile); $stmt = $this->pdo->prepare("SELECT last_updated FROM system_config WHERE key = 'config_timestamp'"); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); if (!$result || $result['last_updated'] < $configModified) { $configData = json_decode(file_get_contents($this->configFile), true); if ($configData) { $this->updateSystemConfig($configData); } } } if (file_exists($this->extensionMapFile)) { $mapModified = filemtime($this->extensionMapFile); $stmt = $this->pdo->prepare("SELECT last_updated FROM system_config WHERE key = 'extension_map_timestamp'"); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); if (!$result || $result['last_updated'] < $mapModified) { $mapData = json_decode(file_get_contents($this->extensionMapFile), true); if ($mapData) { $this->updateExtensionMappings($mapData); } } } if (file_exists($this->iconsFile)) { $iconsModified = filemtime($this->iconsFile); $stmt = $this->pdo->prepare("SELECT last_updated FROM system_config WHERE key = 'icons_timestamp'"); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); if (!$result || $result['last_updated'] < $iconsModified) { $iconsData = json_decode(file_get_contents($this->iconsFile), true); if ($iconsData) { $this->updateIconMappings($iconsData); } } } } private function updateSystemConfig($configData) { $timestamp = time(); $this->pdo->beginTransaction(); try { $stmt = $this->pdo->prepare("INSERT OR REPLACE INTO system_config (key, value, last_updated) VALUES (?, ?, ?)"); $stmt->execute(['config_data', json_encode($configData), $timestamp]); $stmt->execute(['config_timestamp', $timestamp, $timestamp]); if (isset($configData['version'])) { $stmt->execute(['version', $configData['version'], $timestamp]); } if (isset($configData['main'])) { foreach ($configData['main'] as $key => $value) { $stmt->execute(['main_' . $key, json_encode($value), $timestamp]); } } $this->pdo->commit(); } catch (Exception $e) { $this->pdo->rollBack(); error_log("Config update error: " . $e->getMessage()); } } private function updateExtensionMappings($mapData) { $timestamp = time(); $this->pdo->beginTransaction(); try { $this->pdo->exec("DELETE FROM extension_mappings"); $stmt = $this->pdo->prepare("INSERT INTO extension_mappings (extension, indexing_setting, viewing_setting, last_updated) VALUES (?, ?, ?, ?)"); if (isset($mapData['indexing'])) { foreach ($mapData['indexing'] as $ext => $setting) { $viewingSetting = isset($mapData['viewing'][$ext]) ? $mapData['viewing'][$ext] : null; $stmt->execute([$ext, $setting, $viewingSetting, $timestamp]); } } if (isset($mapData['viewing'])) { foreach ($mapData['viewing'] as $ext => $setting) { if (!isset($mapData['indexing'][$ext])) { $stmt->execute([$ext, null, $setting, $timestamp]); } } } $stmt = $this->pdo->prepare("INSERT OR REPLACE INTO system_config (key, value, last_updated) VALUES (?, ?, ?)"); $stmt->execute(['extension_map_timestamp', $timestamp, $timestamp]); $this->pdo->commit(); } catch (Exception $e) { $this->pdo->rollBack(); error_log("Extension map update error: " . $e->getMessage()); } } private function updateIconMappings($iconsData) { $timestamp = time(); $this->pdo->beginTransaction(); try { $this->pdo->exec("DELETE FROM icon_mappings"); $stmt = $this->pdo->prepare("INSERT INTO icon_mappings (identifier, icon_filename, last_updated) VALUES (?, ?, ?)"); foreach ($iconsData as $identifier => $iconFile) { $stmt->execute([$identifier, $iconFile, $timestamp]); } $stmt = $this->pdo->prepare("INSERT OR REPLACE INTO system_config (key, value, last_updated) VALUES (?, ?, ?)"); $stmt->execute(['icons_timestamp', $timestamp, $timestamp]); $this->pdo->commit(); } catch (Exception $e) { $this->pdo->rollBack(); error_log("Icons update error: " . $e->getMessage()); } } public function getConfig($key = null) { try { if ($key === null) { $stmt = $this->pdo->prepare("SELECT value FROM system_config WHERE key = 'config_data'"); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result ? json_decode($result['value'], true) : []; } else { $stmt = $this->pdo->prepare("SELECT value FROM system_config WHERE key = ?"); $stmt->execute([$key]); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result ? json_decode($result['value'], true) : null; } } catch (Exception $e) { error_log("Config get error: " . $e->getMessage()); return null; } } public function getExtensionSetting($extension, $type = 'indexing') { try { $stmt = $this->pdo->prepare("SELECT indexing_setting, viewing_setting FROM extension_mappings WHERE extension = ?"); $stmt->execute([strtolower($extension)]); $result = $stmt->fetch(PDO::FETCH_ASSOC); if ($result) { return $type === 'indexing' ? $result['indexing_setting'] : $result['viewing_setting']; } return null; } catch (Exception $e) { error_log("Extension setting get error: " . $e->getMessage()); return null; } } public function getIconMapping($identifier) { try { $stmt = $this->pdo->prepare("SELECT icon_filename FROM icon_mappings WHERE identifier = ?"); $stmt->execute([strtolower($identifier)]); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result ? $result['icon_filename'] : null; } catch (Exception $e) { error_log("Icon mapping get error: " . $e->getMessage()); return null; } } public function indexPath($path, $filename, $extension, $size, $modified, $isDirectory, $parentPath = null) { try { $timestamp = time(); $stmt = $this->pdo->prepare("INSERT OR REPLACE INTO file_metadata (path, filename, extension, size, modified, is_directory, parent_path, indexed_at, last_verified) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([ $path, $filename, $extension ? strtolower($extension) : null, $size, $modified, $isDirectory ? 1 : 0, $parentPath, $timestamp, $timestamp ]); return true; } catch (Exception $e) { error_log("Index path error: " . $e->getMessage()); return false; } } public function getFileMetadata($path) { try { $stmt = $this->pdo->prepare("SELECT * FROM file_metadata WHERE path = ?"); $stmt->execute([$path]); return $stmt->fetch(PDO::FETCH_ASSOC); } catch (Exception $e) { error_log("Get metadata error: " . $e->getMessage()); return null; } } public function getDirectoryContents($parentPath) { try { if ($parentPath === null || $parentPath === '' || $parentPath === 'ROOT_DIR') { $stmt = $this->pdo->prepare("SELECT * FROM file_metadata WHERE parent_path IS NULL OR parent_path = '' OR parent_path = 'ROOT_DIR' ORDER BY is_directory DESC, filename ASC"); $stmt->execute(); } else { $stmt = $this->pdo->prepare("SELECT * FROM file_metadata WHERE parent_path = ? ORDER BY is_directory DESC, filename ASC"); $stmt->execute([$parentPath]); } return $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (Exception $e) { error_log("Get directory contents error: " . $e->getMessage()); return []; } } public function needsReindex($path, $currentModified) { try { $stmt = $this->pdo->prepare("SELECT modified FROM file_metadata WHERE path = ?"); $stmt->execute([$path]); $result = $stmt->fetch(PDO::FETCH_ASSOC); if (!$result) { return true; } return $result['modified'] < $currentModified; } catch (Exception $e) { return true; } } public function cleanupDeletedPaths($basePath, $existingPaths) { try { $this->pdo->beginTransaction(); $stmt = $this->pdo->prepare("SELECT path FROM file_metadata WHERE path = ? OR path LIKE ?"); $stmt->execute([$basePath, $basePath . '/%']); $indexedPaths = $stmt->fetchAll(PDO::FETCH_COLUMN); $deletedPaths = array_diff($indexedPaths, $existingPaths); if (!empty($deletedPaths)) { $placeholders = implode(',', array_fill(0, count($deletedPaths), '?')); $stmt = $this->pdo->prepare("DELETE FROM file_metadata WHERE path IN ($placeholders)"); $stmt->execute(array_values($deletedPaths)); } $this->pdo->commit(); return count($deletedPaths); } catch (Exception $e) { $this->pdo->rollBack(); error_log("Cleanup error: " . $e->getMessage()); return 0; } } public function getStatistics() { try { $stats = []; $stmt = $this->pdo->query("SELECT COUNT(*) as count FROM file_metadata WHERE is_directory = 0"); $stats['total_files'] = $stmt->fetch(PDO::FETCH_ASSOC)['count']; $stmt = $this->pdo->query("SELECT COUNT(*) as count FROM file_metadata WHERE is_directory = 1"); $stats['total_directories'] = $stmt->fetch(PDO::FETCH_ASSOC)['count']; $stmt = $this->pdo->query("SELECT SUM(size) as total FROM file_metadata WHERE is_directory = 0"); $stats['total_size'] = $stmt->fetch(PDO::FETCH_ASSOC)['total'] ?: 0; if (file_exists($this->dbPath)) { $stats['database_size'] = filesize($this->dbPath); } return $stats; } catch (Exception $e) { error_log("Statistics error: " . $e->getMessage()); return []; } } public function optimize() { try { $this->pdo->exec("VACUUM"); $this->pdo->exec("ANALYZE"); return true; } catch (Exception $e) { error_log("Optimize error: " . $e->getMessage()); return false; } } } ?>