diff --git a/src/Abstract/Model/Connection.php b/src/Abstract/Model/Connection.php index bd584822..70aea8bc 100644 --- a/src/Abstract/Model/Connection.php +++ b/src/Abstract/Model/Connection.php @@ -4,15 +4,22 @@ declare(strict_types=1); namespace Yggverse\Yoda\Abstract\Model; +use \Yggverse\Yoda\Model\Database; use \Yggverse\Yoda\Model\Pool; abstract class Connection implements \Yggverse\Yoda\Interface\Model\Connection { + private Database $_database; + private Pool $_pool; public function __construct( + Database $database, ?Pool $pool = null ) { + // Init database connection to store cached results + $this->_database = $database; + // Use shared memory pool for async operations $this->_pool = $pool ? $pool : new Pool; @@ -228,6 +235,37 @@ abstract class Connection implements \Yggverse\Yoda\Interface\Model\Connection return null; } + public function getCache( + string $request + ): ?object + { + if ($cache = $this->_database->findCache($request)) + { + if (empty($cache[0])) + { + throw new \Exception; + } + + return $cache[0]; + } + + return null; + } + + public function cache( + string $request + ): void + { + $this->_database->renewCache( + $request, + $this->getMime(), + $this->getTitle(), + $this->getSubtitle(), + $this->getTooltip(), + $this->getData() + ); + } + public function reset(): void { $this->_pool->reset(); diff --git a/src/Entity/Browser/Container/Page.php b/src/Entity/Browser/Container/Page.php index f3cf6df6..d52fdf69 100644 --- a/src/Entity/Browser/Container/Page.php +++ b/src/Entity/Browser/Container/Page.php @@ -160,7 +160,9 @@ class Page $this->response->hide(); // Update content using multi-protocol driver - $connection = new Connection; + $connection = new Connection( + $this->container->browser->database + ); // Async request $connection->request( diff --git a/src/Interface/Model/Connection.php b/src/Interface/Model/Connection.php index 8d4fe526..a6857909 100644 --- a/src/Interface/Model/Connection.php +++ b/src/Interface/Model/Connection.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Yggverse\Yoda\Interface\Model; +use \Yggverse\Yoda\Model\Database; use \Yggverse\Yoda\Model\Pool; /* @@ -13,6 +14,7 @@ use \Yggverse\Yoda\Model\Pool; interface Connection { public function __construct( + Database $database, ?Pool $pool = null ); @@ -74,6 +76,14 @@ interface Connection public function getLength(): ?int; + public function getCache( + string $request + ): ?object; + + public function cache( + string $request + ): void; + public function reset(): void; public function close(): void; diff --git a/src/Model/Connection/Gemini.php b/src/Model/Connection/Gemini.php index 8e5e36ba..295bc6e9 100644 --- a/src/Model/Connection/Gemini.php +++ b/src/Model/Connection/Gemini.php @@ -109,11 +109,16 @@ class Gemini $address->get() ); - // Update content data + // Set data $this->_connection->setData( $response->getBody() ); + // Cache + $this->_connection->cache( + $address->get() + ); + break; case 31: // redirect @@ -149,35 +154,65 @@ class Gemini default: - $this->_connection->setTitle( - _('Oops!') - ); + // Try cache + if ($cache = $this->_connection->getCache($address->get())) + { + $this->_connection->setTitle( + $cache->title + ); - $this->_connection->setSubtitle( - $address->getHost() - ); + $this->_connection->setSubtitle( + date( + 'c', + $cache->time + ) # $cache->subtitle + ); - $this->_connection->setTooltip( - sprintf( - 'Could not open request (code: %d)', - intval( - $response->getCode() + $this->_connection->setTooltip( + $cache->tooltip + ); + + $this->_connection->setData( + $cache->data + ); + + $this->_connection->setMime( + $cache->mime + ); + } + + else + { + $this->_connection->setTitle( + _('Oops!') + ); + + $this->_connection->setSubtitle( + $address->getHost() + ); + + $this->_connection->setTooltip( + sprintf( + 'Could not open request (code: %d)', + intval( + $response->getCode() + ) ) - ) - ); + ); - $this->_connection->setData( - sprintf( - 'Could not open request (code: %d)', - intval( - $response->getCode() + $this->_connection->setData( + sprintf( + 'Could not open request (code: %d)', + intval( + $response->getCode() + ) ) - ) - ); + ); - $this->_connection->setMime( - Filesystem::MIME_TEXT_GEMINI - ); + $this->_connection->setMime( + Filesystem::MIME_TEXT_GEMINI + ); + } } $this->_connection->setCompleted( diff --git a/src/Model/Connection/Nex.php b/src/Model/Connection/Nex.php index fb0c5ca4..55a4a856 100644 --- a/src/Model/Connection/Nex.php +++ b/src/Model/Connection/Nex.php @@ -31,6 +31,7 @@ class Nex $timeout ); + // Success if ($response) { // Detect MIME type @@ -67,9 +68,42 @@ class Nex $address->get() ); + // Set data $this->_connection->setData( $response ); + + // Cache + $this->_connection->cache( + $address->get() + ); + } + + // Try cache + if ($cache = $this->_connection->getCache()) + { + $this->_connection->setTitle( + $cache->title + ); + + $this->_connection->setSubtitle( + date( + 'c', + $cache->time + ) # $cache->subtitle + ); + + $this->_connection->setTooltip( + $cache->tooltip + ); + + $this->_connection->setData( + $cache->data + ); + + $this->_connection->setMime( + $cache->mime + ); } else diff --git a/src/Model/Database.php b/src/Model/Database.php index 9d37c28f..212f9b57 100644 --- a/src/Model/Database.php +++ b/src/Model/Database.php @@ -6,7 +6,7 @@ namespace Yggverse\Yoda\Model; class Database { - private \PDO $_database; + private \PDO $_connection; private bool $_exists; @@ -21,7 +21,7 @@ class Database ); // Init database connection - $this->_database = new \PDO( + $this->_connection = new \PDO( sprintf( 'sqlite:%s', $filename @@ -30,28 +30,32 @@ class Database $password ); - $this->_database->setAttribute( + $this->_connection->setAttribute( \PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION ); - $this->_database->setAttribute( + $this->_connection->setAttribute( \PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ ); // Init tables - $this->_database->query(' + $this->_connection->query(' CREATE TABLE IF NOT EXISTS `cache` ( - `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - `time` INTEGER NOT NULL, - `request` VARCHAR(1024), - `data` BLOB + `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + `time` INTEGER NOT NULL, + `request` VARCHAR(1024), + `mime` VARCHAR(255), + `title` VARCHAR(255), + `subtitle` VARCHAR(255), + `tooltip` VARCHAR(255), + `data` BLOB ); '); - $this->_database->query(' + $this->_connection->query(' CREATE TABLE IF NOT EXISTS `history` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -61,7 +65,7 @@ class Database ) '); - $this->_database->query(' + $this->_connection->query(' CREATE TABLE IF NOT EXISTS `session` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -83,24 +87,48 @@ class Database // Cache public function addCache( ?string $request = null, + ?string $mime = null, + ?string $title = null, + ?string $subtitle = null, + ?string $tooltip = null, ?string $data = null, ?int $time = null ): int { - $query = $this->_database->prepare( - 'INSERT INTO `cache` (`time`, `request`, `data`) VALUES (:time, :request, :data)' + $query = $this->_connection->prepare( + 'INSERT INTO `cache` ( + `time`, + `request`, + `mime`, + `title`, + `subtitle`, + `tooltip`, + `data` + ) VALUES ( + :time, + :request, + :mime, + :title, + :subtitle, + :tooltip, + :data + )' ); $query->execute( [ - ':time' => $time ? $time : time(), - ':request' => $request, - ':data' => $data + ':time' => $time ? $time : time(), + ':request' => $request, + ':mime' => $mime, + ':title' => $title, + ':subtitle' => $subtitle, + ':tooltip' => $tooltip, + ':data' => $data ] ); return intval( - $this->_database->lastInsertId() + $this->_connection->lastInsertId() ); } @@ -110,7 +138,7 @@ class Database int $limit = 1000 ): array { - $query = $this->_database->prepare( + $query = $this->_connection->prepare( sprintf( 'SELECT * FROM `cache` WHERE `request` LIKE :request @@ -138,7 +166,7 @@ class Database int $id ): int { - $query = $this->_database->query( + $query = $this->_connection->query( sprintf( 'DELETE FROM `cache` WHERE `id` = %d', $id @@ -152,7 +180,7 @@ class Database int $timeout = 0 ): int { - $query = $this->_database->query( + $query = $this->_connection->query( sprintf( 'DELETE FROM `cache` WHERE `time` + %d < %d', $timeout, @@ -165,11 +193,16 @@ class Database public function renewCache( string $request, - ?string $title = null + ?string $mime = null, + ?string $title = null, + ?string $subtitle = null, + ?string $tooltip = null, + ?string $data = null, + ?int $time = null ): void { // Find same records match URL - $query = $this->_database->prepare( + $query = $this->_connection->prepare( 'SELECT * FROM `cache` WHERE `request` LIKE :request' ); @@ -190,7 +223,12 @@ class Database // Add new record $this->addCache( $request, - $data + $mime, + $title, + $subtitle, + $tooltip, + $data, + $time ); } @@ -200,7 +238,7 @@ class Database ?string $title = null ): int { - $query = $this->_database->prepare( + $query = $this->_connection->prepare( 'INSERT INTO `history` (`time`, `url`, `title`) VALUES (:time, :url, :title)' ); @@ -213,7 +251,7 @@ class Database ); return intval( - $this->_database->lastInsertId() + $this->_connection->lastInsertId() ); } @@ -223,7 +261,7 @@ class Database int $limit = 1000 ): array { - $query = $this->_database->prepare( + $query = $this->_connection->prepare( sprintf( 'SELECT * FROM `history` WHERE `url` LIKE :value OR `title` LIKE :value @@ -250,7 +288,7 @@ class Database int $id ): int { - $query = $this->_database->query( + $query = $this->_connection->query( sprintf( 'DELETE FROM `history` WHERE `id` = %d', $id @@ -264,7 +302,7 @@ class Database int $timeout = 0 ): int { - $query = $this->_database->query( + $query = $this->_connection->query( sprintf( 'DELETE FROM `history` WHERE `time` + %d < %d', $timeout, @@ -282,7 +320,7 @@ class Database ): void { // Find same records match URL - $query = $this->_database->prepare( + $query = $this->_connection->prepare( 'SELECT * FROM `history` WHERE `url` LIKE :url' ); @@ -313,7 +351,7 @@ class Database ?int $time = null ): int { - $query = $this->_database->prepare( + $query = $this->_connection->prepare( 'INSERT INTO `session` (`time`, `request`) VALUES (:time, :request)' ); @@ -325,13 +363,13 @@ class Database ); return intval( - $this->_database->lastInsertId() + $this->_connection->lastInsertId() ); } public function getSession(): array { - $query = $this->_database->query( + $query = $this->_connection->query( 'SELECT * FROM `session`' ); @@ -345,7 +383,7 @@ class Database public function cleanSession(): int { - $query = $this->_database->query( + $query = $this->_connection->query( 'DELETE FROM `session`' );