diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Database/Database.php | 98 | ||||
-rw-r--r-- | src/Database/DatabaseServiceProvider.php | 16 | ||||
-rw-r--r-- | src/Database/Db.php | 1 | ||||
-rw-r--r-- | src/Database/Migration/Migrate.php | 40 | ||||
-rw-r--r-- | src/Database/Migration/MigrationServiceProvider.php | 11 | ||||
-rw-r--r-- | src/Http/SessionHandlers/AbstractHandler.php | 75 | ||||
-rw-r--r-- | src/Http/SessionHandlers/DatabaseHandler.php | 108 | ||||
-rw-r--r-- | src/Http/SessionServiceProvider.php | 21 | ||||
-rw-r--r-- | src/Models/BaseModel.php | 16 |
9 files changed, 359 insertions, 27 deletions
diff --git a/src/Database/Database.php b/src/Database/Database.php new file mode 100644 index 00000000..407a8bf9 --- /dev/null +++ b/src/Database/Database.php @@ -0,0 +1,98 @@ +<?php + +namespace Engelsystem\Database; + +use Illuminate\Database\Connection as DatabaseConnection; +use PDO; + +class Database +{ + /** @var DatabaseConnection */ + protected $connection; + + /** + * @param DatabaseConnection $connection + */ + public function __construct(DatabaseConnection $connection) + { + $this->connection = $connection; + } + + /** + * Run a select query + * + * @param string $query + * @param array $bindings + * @return object[] + */ + public function select($query, array $bindings = []) + { + return $this->connection->select($query, $bindings); + } + + /** + * Run a select query and return only the first result or null if no result is found. + * + * @param string $query + * @param array $bindings + * @return object|null + */ + public function selectOne($query, array $bindings = []) + { + return $this->connection->selectOne($query, $bindings); + } + + /** + * Run an insert query + * + * @param string $query + * @param array $bindings + * @return bool + */ + public function insert($query, array $bindings = []) + { + return $this->connection->insert($query, $bindings); + } + + /** + * Run an update query + * + * @param string $query + * @param array $bindings + * @return int + */ + public function update($query, array $bindings = []) + { + return $this->connection->update($query, $bindings); + } + + /** + * Run a delete query + * + * @param string $query + * @param array $bindings + * @return int + */ + public function delete($query, array $bindings = []) + { + return $this->connection->delete($query, $bindings); + } + + /** + * Get the PDO instance + * + * @return PDO + */ + public function getPdo() + { + return $this->connection->getPdo(); + } + + /** + * @return DatabaseConnection + */ + public function getConnection() + { + return $this->connection; + } +} diff --git a/src/Database/DatabaseServiceProvider.php b/src/Database/DatabaseServiceProvider.php index 7328bc4e..b3c33588 100644 --- a/src/Database/DatabaseServiceProvider.php +++ b/src/Database/DatabaseServiceProvider.php @@ -5,6 +5,7 @@ namespace Engelsystem\Database; use Engelsystem\Container\ServiceProvider; use Exception; use Illuminate\Database\Capsule\Manager as CapsuleManager; +use Illuminate\Database\Connection as DatabaseConnection; use PDOException; class DatabaseServiceProvider extends ServiceProvider @@ -30,14 +31,25 @@ class DatabaseServiceProvider extends ServiceProvider $capsule->bootEloquent(); $capsule->getConnection()->useDefaultSchemaGrammar(); + $pdo = null; try { - $capsule->getConnection()->getPdo(); + $pdo = $capsule->getConnection()->getPdo(); } catch (PDOException $e) { $this->exitOnError(); } - $this->app->instance('db', $capsule); + $this->app->instance(CapsuleManager::class, $capsule); + $this->app->instance(Db::class, $capsule); Db::setDbManager($capsule); + + $connection = $capsule->getConnection(); + $this->app->instance(DatabaseConnection::class, $connection); + + $database = $this->app->make(Database::class); + $this->app->instance(Database::class, $database); + $this->app->instance('db', $database); + $this->app->instance('db.pdo', $pdo); + $this->app->instance('db.connection', $connection); } /** diff --git a/src/Database/Db.php b/src/Database/Db.php index c0871e68..d007f1e5 100644 --- a/src/Database/Db.php +++ b/src/Database/Db.php @@ -6,6 +6,7 @@ use Illuminate\Database\Capsule\Manager as CapsuleManager; use Illuminate\Database\Connection as DatabaseConnection; use PDO; +/** @deprecated */ class Db { /** @var CapsuleManager */ diff --git a/src/Database/Migration/Migrate.php b/src/Database/Migration/Migrate.php index 3a08bb6e..9c6d3e43 100644 --- a/src/Database/Migration/Migrate.php +++ b/src/Database/Migration/Migrate.php @@ -18,7 +18,7 @@ class Migrate protected $app; /** @var SchemaBuilder */ - protected $scheme; + protected $schema; /** @var callable */ protected $output; @@ -29,13 +29,13 @@ class Migrate /** * Migrate constructor * - * @param SchemaBuilder $scheme + * @param SchemaBuilder $schema * @param Application $app */ - public function __construct(SchemaBuilder $scheme, Application $app) + public function __construct(SchemaBuilder $schema, Application $app) { $this->app = $app; - $this->scheme = $scheme; + $this->schema = $schema; $this->output = function () { }; } @@ -77,6 +77,21 @@ class Migrate } /** + * Setup migration tables + */ + public function initMigration() + { + if ($this->schema->hasTable($this->table)) { + return; + } + + $this->schema->create($this->table, function (Blueprint $table) { + $table->increments('id'); + $table->string('migration'); + }); + } + + /** * Get all migrated migrations * * @return Collection @@ -156,28 +171,13 @@ class Migrate } /** - * Setup migration tables - */ - protected function initMigration() - { - if ($this->scheme->hasTable($this->table)) { - return; - } - - $this->scheme->create($this->table, function (Blueprint $table) { - $table->increments('id'); - $table->string('migration'); - }); - } - - /** * Init a table query * * @return Builder */ protected function getTableQuery() { - return $this->scheme->getConnection()->table($this->table); + return $this->schema->getConnection()->table($this->table); } /** diff --git a/src/Database/Migration/MigrationServiceProvider.php b/src/Database/Migration/MigrationServiceProvider.php index 15d06eaf..310b2114 100644 --- a/src/Database/Migration/MigrationServiceProvider.php +++ b/src/Database/Migration/MigrationServiceProvider.php @@ -3,16 +3,19 @@ namespace Engelsystem\Database\Migration; use Engelsystem\Container\ServiceProvider; -use Engelsystem\Database\Db; +use Engelsystem\Database\Database; use Illuminate\Database\Schema\Builder as SchemaBuilder; class MigrationServiceProvider extends ServiceProvider { public function register() { - $schema = Db::connection()->getSchemaBuilder(); - $this->app->instance('db.scheme', $schema); - $this->app->bind(SchemaBuilder::class, 'db.scheme'); + /** @var Database $database */ + $database = $this->app->get(Database::class); + $schema = $database->getConnection()->getSchemaBuilder(); + + $this->app->instance('db.schema', $schema); + $this->app->bind(SchemaBuilder::class, 'db.schema'); $migration = $this->app->make(Migrate::class); $this->app->instance('db.migration', $migration); diff --git a/src/Http/SessionHandlers/AbstractHandler.php b/src/Http/SessionHandlers/AbstractHandler.php new file mode 100644 index 00000000..135d0d43 --- /dev/null +++ b/src/Http/SessionHandlers/AbstractHandler.php @@ -0,0 +1,75 @@ +<?php + +namespace Engelsystem\Http\SessionHandlers; + +use SessionHandlerInterface; + +abstract class AbstractHandler implements SessionHandlerInterface +{ + /** @var string */ + protected $name; + + /** @var string */ + protected $sessionPath; + + /** + * Bootstrap the session handler + * + * @param string $sessionPath + * @param string $name + * @return bool + */ + public function open($sessionPath, $name): bool + { + $this->name = $name; + $this->sessionPath = $sessionPath; + + return true; + } + + /** + * Shutdown the session handler + * + * @return bool + */ + public function close(): bool + { + return true; + } + + /** + * Remove old sessions + * + * @param int $maxLifetime + * @return bool + */ + public function gc($maxLifetime): bool + { + return true; + } + + /** + * Read session data + * + * @param string $id + * @return string + */ + abstract public function read($id): string; + + /** + * Write session data + * + * @param string $id + * @param string $data + * @return bool + */ + abstract public function write($id, $data): bool; + + /** + * Delete a session + * + * @param string $id + * @return bool + */ + abstract public function destroy($id): bool; +} diff --git a/src/Http/SessionHandlers/DatabaseHandler.php b/src/Http/SessionHandlers/DatabaseHandler.php new file mode 100644 index 00000000..8df70287 --- /dev/null +++ b/src/Http/SessionHandlers/DatabaseHandler.php @@ -0,0 +1,108 @@ +<?php + +namespace Engelsystem\Http\SessionHandlers; + +use Engelsystem\Database\Database; +use Illuminate\Database\Query\Builder as QueryBuilder; + +class DatabaseHandler extends AbstractHandler +{ + /** @var Database */ + protected $database; + + /** + * @param Database $database + */ + public function __construct(Database $database) + { + $this->database = $database; + } + + /** + * {@inheritdoc} + */ + public function read($id): string + { + $session = $this->getQuery() + ->where('id', '=', $id) + ->first(); + + return $session ? $session->payload : ''; + } + + /** + * {@inheritdoc} + */ + public function write($id, $data): bool + { + $values = [ + 'payload' => $data, + 'last_activity' => $this->getCurrentTimestamp(), + ]; + + $session = $this->getQuery() + ->where('id', '=', $id) + ->first(); + + if (!$session) { + return $this->getQuery() + ->insert($values + [ + 'id' => $id, + ]); + } + + $this->getQuery() + ->where('id', '=', $id) + ->update($values); + + // The update return can't be used directly because it won't change if the second call is in the same second + return true; + } + + /** + * {@inheritdoc} + */ + public function destroy($id): bool + { + $this->getQuery() + ->where('id', '=', $id) + ->delete(); + + return true; + } + + /** + * {@inheritdoc} + */ + public function gc($maxLifetime): bool + { + $timestamp = $this->getCurrentTimestamp(-$maxLifetime); + + $this->getQuery() + ->where('last_activity', '<', $timestamp) + ->delete(); + + return true; + } + + /** + * @return QueryBuilder + */ + protected function getQuery(): QueryBuilder + { + return $this->database + ->getConnection() + ->table('sessions'); + } + + /** + * Format the SQL timestamp + * + * @param int $diff + * @return string + */ + protected function getCurrentTimestamp(int $diff = 0): string + { + return date('Y-m-d H:i:s', strtotime(sprintf('%+d seconds', $diff))); + } +} diff --git a/src/Http/SessionServiceProvider.php b/src/Http/SessionServiceProvider.php index 59121a3b..c2e09624 100644 --- a/src/Http/SessionServiceProvider.php +++ b/src/Http/SessionServiceProvider.php @@ -2,7 +2,9 @@ namespace Engelsystem\Http; +use Engelsystem\Config\Config; use Engelsystem\Container\ServiceProvider; +use Engelsystem\Http\SessionHandlers\DatabaseHandler; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; @@ -38,7 +40,24 @@ class SessionServiceProvider extends ServiceProvider return $this->app->make(MockArraySessionStorage::class); } - return $this->app->make(NativeSessionStorage::class, ['options' => ['cookie_httponly' => true]]); + /** @var Config $config */ + $config = $this->app->get('config'); + $sessionConfig = $config->get('session'); + + $handler = null; + switch ($sessionConfig['driver']) { + case 'pdo': + $handler = $this->app->make(DatabaseHandler::class); + break; + } + + return $this->app->make(NativeSessionStorage::class, [ + 'options' => [ + 'cookie_httponly' => true, + 'name' => $sessionConfig['name'], + ], + 'handler' => $handler, + ]); } /** diff --git a/src/Models/BaseModel.php b/src/Models/BaseModel.php index cf718e4f..d5ded428 100644 --- a/src/Models/BaseModel.php +++ b/src/Models/BaseModel.php @@ -2,6 +2,8 @@ namespace Engelsystem\Models; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; abstract class BaseModel extends Model @@ -10,6 +12,8 @@ abstract class BaseModel extends Model public $timestamps = false; /** + * Create a new model + * * @param array $attributes * @return BaseModel */ @@ -20,4 +24,16 @@ abstract class BaseModel extends Model return $instance; } + + /** + * Find a model by its primary key + * + * @param mixed $id + * @param array $columns + * @return Builder|Builder[]|Collection|Model|null + */ + public static function find($id, $columns = ['*']) + { + return static::query()->find($id, $columns); + } } |