diff --git a/include/nc_connector_webdav.inc.php b/include/nc_connector_webdav.inc.php index fb6908c..0b03270 100644 --- a/include/nc_connector_webdav.inc.php +++ b/include/nc_connector_webdav.inc.php @@ -5,10 +5,89 @@ if (!defined('PHPWG_ROOT_PATH')) } /** - * Create a disabled WebDAV-backed connector beside the existing local modes. + * Return the only existing local connector as migration fallback. * - * This deliberately does not activate, migrate or modify any existing - * connection. It only persists the data required for the parallel WebDAV path. + * The 0.9.6.2 migration path is deliberately conservative: automatic pairing + * only happens when there is exactly one local connection. Its enabled/state + * flags are never changed here, so the proven local path keeps running while + * WebDAV is introduced beside it. + */ +function bratonien_tools_nc_connector_single_local_fallback() +{ + bratonien_tools_nc_connector_ensure_table(); + $table = bratonien_tools_nc_connector_table(); + $result = pwg_query("SELECT id, enabled, takeover_state, config_json FROM `$table` WHERE adapter='local' ORDER BY id"); + $rows = array(); + + while ($row = pwg_db_fetch_assoc($result)) + { + $rows[] = $row; + if (count($rows) > 1) return null; + } + + if (count($rows) !== 1) return null; + + $row = $rows[0]; + $config = json_decode((string)$row['config_json'], true); + if (!is_array($config)) $config = array(); + + return array( + 'id'=>(int)$row['id'], + 'enabled'=>(bool)$row['enabled'], + 'takeover_state'=>(string)$row['takeover_state'], + 'config'=>$config, + ); +} + +/** + * Link the new WebDAV connection with the single existing local connection. + * + * This is metadata only. The legacy connection is explicitly left untouched + * as an always-available fallback until a later, separately approved cutover. + */ +function bratonien_tools_nc_connector_pair_migration_fallback($webdav_id, array &$webdav_config, $now) +{ + $legacy = bratonien_tools_nc_connector_single_local_fallback(); + if (!$legacy) return null; + + $legacy_id = (int)$legacy['id']; + if ($legacy_id < 1 || $legacy_id === (int)$webdav_id) return null; + + $webdav_config['migration'] = array( + 'role'=>'webdav-primary-candidate', + 'legacy_fallback_connection_id'=>$legacy_id, + 'fallback_policy'=>'keep-running', + 'paired_at'=>(string)$now, + 'cutover_state'=>'parallel', + ); + + $legacy_config = $legacy['config']; + $legacy_config['migration'] = array( + 'role'=>'legacy-fallback', + 'webdav_successor_connection_id'=>(int)$webdav_id, + 'fallback_policy'=>'keep-running', + 'paired_at'=>(string)$now, + 'cutover_state'=>'parallel', + ); + + $legacy_json = json_encode($legacy_config, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + if (!is_string($legacy_json)) + { + throw new RuntimeException('Die bestehende Verbindung konnte nicht als Migrations-Fallback markiert werden.'); + } + + $table = bratonien_tools_nc_connector_table(); + pwg_query("UPDATE `$table` SET config_json='".pwg_db_real_escape_string($legacy_json)."', updated='".pwg_db_real_escape_string((string)$now)."' WHERE id=".$legacy_id." LIMIT 1"); + + return $legacy_id; +} + +/** + * Create a WebDAV-backed connector beside the existing local mode. + * + * Since 0.9.6.2, when exactly one local connection exists, the new WebDAV + * connection is automatically paired with it for migration. The local + * connection remains untouched and keeps running as fallback. */ function bratonien_tools_nc_connector_create_webdav_placeholder_from_wizard() { @@ -116,18 +195,36 @@ function bratonien_tools_nc_connector_create_webdav_placeholder_from_wizard() $id = (int)pwg_db_insert_id(); if ($id < 1) throw new RuntimeException('Die WebDAV-Testverbindung konnte nicht eindeutig angelegt werden.'); - $config['state_dir'] = '/var/lib/bratonien-tools/nc-connector/connection-'.$id; - $config['status_file'] = $config['state_dir'].'/connector-status.json'; - $config_json = json_encode($config, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); - if (!is_string($config_json)) + try + { + $config['state_dir'] = '/var/lib/bratonien-tools/nc-connector/connection-'.$id; + $config['status_file'] = $config['state_dir'].'/connector-status.json'; + $legacy_fallback_id = bratonien_tools_nc_connector_pair_migration_fallback($id, $config, $now); + + $config_json = json_encode($config, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + if (!is_string($config_json)) + { + throw new RuntimeException('Die WebDAV-Testverbindung konnte nach dem Anlegen nicht serialisiert werden.'); + } + pwg_query("UPDATE `$table` SET config_json='".pwg_db_real_escape_string($config_json)."' WHERE id=".$id." LIMIT 1"); + } + catch (Throwable $e) { pwg_query("DELETE FROM `$table` WHERE id=".$id." LIMIT 1"); - throw new RuntimeException('Die WebDAV-Testverbindung konnte nach dem Anlegen nicht serialisiert werden.'); + throw $e; + } + + if ($legacy_fallback_id !== null) + { + return array( + 'connection_id'=>$id, + 'legacy_fallback_connection_id'=>$legacy_fallback_id, + 'message'=>'WebDAV-Verbindung wurde parallel angelegt. Die bestehende lokale Verbindung #'.$legacy_fallback_id.' bleibt unverändert als laufender Fallback erhalten.', + ); } - pwg_query("UPDATE `$table` SET config_json='".pwg_db_real_escape_string($config_json)."' WHERE id=".$id." LIMIT 1"); return array( 'connection_id'=>$id, - 'message'=>'Parallele WebDAV-Testverbindung wurde deaktiviert angelegt. Bestehende Verbindungen blieben unverändert.', + 'message'=>'Parallele WebDAV-Verbindung wurde angelegt. Bestehende Verbindungen blieben unverändert.', ); }