로그인
KO
<?phpnamespace App\Model;use JumPHP\Kernel\Engine;/** * Everything the windows share: the servers (saved in var/servers.json), their connections, the Events log, the navigation * history (Back / Forward). One for the whole app (a service). */final class Session{    /** @var list<Connection> */    public array $connections = [];    /** @var list<LogEntry> newest last */    public array $log = [];    public float $clock = 0;    /** the one of the app: the dialogs tick it while they are on top of the window */    public static ?Session $current = null;    public function __construct()    {        self::$current = $this;    }    private bool $loaded = false;    /** the saved passwords' keys (src/Model/Keyring.php) */    private ?Keyring $keyring = null;    public function keyring(): Keyring    {        return $this->keyring ??= new Keyring(Engine::get()->storage);    }    public function load(): void    {        if ($this->loaded) {            return;        }        $this->loaded = true;        foreach ((array)Engine::get()->storage->readJson('servers.json', []) as $row) {            if (is_array($row) && ($row['host'] ?? '') !== '') {                $this->connections[] = new Connection(ServerProfile::fromArray($row), $this);            }        }        $this->keyring()->restore($this);       // the sealed passwords opened (or asked for: MasterPasswordForm), clear ones of old files sealed    }    /** Forgets everything (tests). */    public function reset(): void    {        foreach ($this->connections as $c) {            $c->disconnect(false);        }        $this->connections = [];        $this->log = [];        $this->loaded = true;        $this->keyring = null;    }    public function save(): void    {        Engine::get()->storage->writeJson('servers.json', array_map(fn (Connection $c) => $c->profile->toArray($this->keyring()), $this->connections));    }    /** A server added (or found again): connected at once. */    public function add(ServerProfile $profile): Connection    {        foreach ($this->connections as $c) {            if ($c->profile->key() === $profile->key()) {                $c->profile = $profile;                $this->save();                return $c;            }        }        $connection = new Connection($profile, $this);        $this->connections[] = $connection;        $this->save();        return $connection;    }    public function remove(Connection $connection): void    {        $connection->disconnect();        $this->connections = array_values(array_filter($this->connections, fn ($c) => $c !== $connection));        $this->save();    }    public function tick(float $dt): void    {        $this->clock += $dt;        foreach ($this->connections as $c) {            $c->tick($dt);        }    }    public function log(string $title, string $server, ?string $target = null, string $status = LogEntry::DONE, string $detail = ''): LogEntry    {        $entry = new LogEntry($title, $server, $target, $this->clock);        $entry->status = $status;        $entry->detail = $detail;        if ($status !== LogEntry::RUNNING) {            $entry->progress = 1;            $entry->finished = $this->clock;        }        $this->log[] = $entry;        if (count($this->log) > 300) {            array_shift($this->log);        }        return $entry;    }    public function running(): int    {        return count(array_filter($this->log, fn (LogEntry $e) => $e->status === LogEntry::RUNNING));    }    /** The connection that holds an object. */    public function connectionOf(string $ref): ?Connection    {        foreach ($this->connections as $c) {            if ($c->cache->get($ref) !== null) {                return $c;            }        }        return null;    }    public function version(): int    {        $v = count($this->connections) * 1000003;        foreach ($this->log as $e) {            $v += $e->id * 7 + (int)($e->progress * 100) + strlen($e->status) * 13;        }        foreach ($this->connections as $i => $c) {            $v += $c->cache->version * ($i + 1) + strlen($c->state) * 31;        }        return $v;    }}