Session: Added Symfony PDO backend
This commit is contained in:
parent
edeab5e75f
commit
104e4f4c43
|
@ -137,4 +137,13 @@ return [
|
|||
'3XL' => '3XL',
|
||||
'4XL' => '4XL'
|
||||
],
|
||||
|
||||
// Session config
|
||||
'session' => [
|
||||
// Supported: pdo or native
|
||||
'driver' => env('SESSION_DRIVER', 'pdo'),
|
||||
|
||||
// Cookie name
|
||||
'name' => 'session',
|
||||
],
|
||||
];
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Engelsystem\Database\Migration\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class CreateSessionsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$this->schema->create('sessions', function (Blueprint $table) {
|
||||
$table->string('id')->unique();
|
||||
$table->text('payload');
|
||||
$table->integer('last_activity');
|
||||
$table->integer('lifetime');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$this->schema->dropIfExists('sessions');
|
||||
}
|
||||
}
|
|
@ -31,8 +31,9 @@ class DatabaseServiceProvider extends ServiceProvider
|
|||
$capsule->bootEloquent();
|
||||
$capsule->getConnection()->useDefaultSchemaGrammar();
|
||||
|
||||
$pdo = null;
|
||||
try {
|
||||
$capsule->getConnection()->getPdo();
|
||||
$pdo = $capsule->getConnection()->getPdo();
|
||||
} catch (PDOException $e) {
|
||||
$this->exitOnError();
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
namespace Engelsystem\Http;
|
||||
|
||||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
|
||||
|
@ -38,7 +40,35 @@ 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;
|
||||
$driver = $sessionConfig['driver'];
|
||||
|
||||
switch ($driver) {
|
||||
case 'pdo':
|
||||
$handler = $this->app->make(PdoSessionHandler::class, [
|
||||
'pdoOrDsn' => $this->app->get('db.pdo'),
|
||||
'options' => [
|
||||
'db_table' => 'sessions',
|
||||
'db_id_col' => 'id',
|
||||
'db_data_col' => 'payload',
|
||||
'db_lifetime_col' => 'lifetime',
|
||||
'db_time_col' => 'last_activity',
|
||||
],
|
||||
]);
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->app->make(NativeSessionStorage::class, [
|
||||
'options' => [
|
||||
'cookie_httponly' => true,
|
||||
'name' => $sessionConfig['name'],
|
||||
],
|
||||
'handler' => $handler,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Engelsystem\Test\Unit\Database;
|
||||
|
||||
use Engelsystem\Application;
|
||||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Database\Database;
|
||||
use Engelsystem\Database\DatabaseServiceProvider;
|
||||
|
@ -10,6 +11,7 @@ use Engelsystem\Test\Unit\ServiceProviderTest;
|
|||
use Exception;
|
||||
use Illuminate\Database\Capsule\Manager as CapsuleManager;
|
||||
use Illuminate\Database\Connection;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
|
||||
|
@ -117,12 +119,12 @@ class DatabaseServiceProviderTest extends ServiceProviderTest
|
|||
$this->setExpects($connection, 'useDefaultSchemaGrammar');
|
||||
$connection->expects($this->once())
|
||||
->method('getPdo')
|
||||
->willReturnCallback(function () use ($getPdoThrowException) {
|
||||
->willReturnCallback(function () use ($getPdoThrowException, $pdo) {
|
||||
if ($getPdoThrowException) {
|
||||
throw new PDOException();
|
||||
}
|
||||
|
||||
return '';
|
||||
return $pdo;
|
||||
});
|
||||
$this->setExpects($dbManager, 'getConnection', [], $connection, $this->atLeastOnce());
|
||||
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
namespace Engelsystem\Test\Unit\Http;
|
||||
|
||||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Http\Request;
|
||||
use Engelsystem\Http\SessionServiceProvider;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use PDO;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface as StorageInterface;
|
||||
|
@ -23,6 +26,9 @@ class SessionServiceProviderTest extends ServiceProviderTest
|
|||
|
||||
$sessionStorage = $this->getMockForAbstractClass(StorageInterface::class);
|
||||
$sessionStorage2 = $this->getMockForAbstractClass(StorageInterface::class);
|
||||
$pdoSessionHandler = $this->getMockBuilder(PdoSessionHandler::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$session = $this->getSessionMock();
|
||||
$request = $this->getRequestMock();
|
||||
|
@ -32,22 +38,54 @@ class SessionServiceProviderTest extends ServiceProviderTest
|
|||
->setConstructorArgs([$app])
|
||||
->setMethods(['isCli'])
|
||||
->getMock();
|
||||
$serviceProvider->expects($this->exactly(2))
|
||||
->method('isCli')
|
||||
->willReturnOnConsecutiveCalls(true, false);
|
||||
|
||||
$app->expects($this->exactly(4))
|
||||
/** @var Config|MockObject $config */
|
||||
$config = $this->createMock(Config::class);
|
||||
/** @var PDO|MockObject $pdo */
|
||||
$pdo = $this->getMockBuilder(PDO::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$serviceProvider->expects($this->exactly(3))
|
||||
->method('isCli')
|
||||
->willReturnOnConsecutiveCalls(true, false, false);
|
||||
|
||||
$app->expects($this->exactly(7))
|
||||
->method('make')
|
||||
->withConsecutive(
|
||||
[MockArraySessionStorage::class],
|
||||
[Session::class],
|
||||
[NativeSessionStorage::class, ['options' => ['cookie_httponly' => true]]],
|
||||
[
|
||||
NativeSessionStorage::class,
|
||||
['options' => ['cookie_httponly' => true, 'name' => 'session'], 'handler' => null]
|
||||
],
|
||||
[Session::class],
|
||||
[
|
||||
PdoSessionHandler::class,
|
||||
[
|
||||
'pdoOrDsn' => $pdo,
|
||||
'options' => [
|
||||
'db_table' => 'sessions',
|
||||
'db_id_col' => 'id',
|
||||
'db_data_col' => 'payload',
|
||||
'db_lifetime_col' => 'lifetime',
|
||||
'db_time_col' => 'last_activity',
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
NativeSessionStorage::class,
|
||||
['options' => ['cookie_httponly' => true, 'name' => 'foobar'], 'handler' => $pdoSessionHandler]
|
||||
],
|
||||
[Session::class]
|
||||
)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
$sessionStorage,
|
||||
$session,
|
||||
$sessionStorage2,
|
||||
$session,
|
||||
$pdoSessionHandler,
|
||||
$sessionStorage2,
|
||||
$session
|
||||
);
|
||||
$app->expects($this->atLeastOnce())
|
||||
|
@ -58,13 +96,40 @@ class SessionServiceProviderTest extends ServiceProviderTest
|
|||
['session', $session]
|
||||
);
|
||||
|
||||
$app->expects($this->exactly(6))
|
||||
->method('get')
|
||||
->withConsecutive(
|
||||
['request'],
|
||||
['config'],
|
||||
['request'],
|
||||
['config'],
|
||||
['db.pdo'],
|
||||
['request']
|
||||
)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
$request,
|
||||
$config,
|
||||
$request,
|
||||
$config,
|
||||
$pdo,
|
||||
$request
|
||||
);
|
||||
|
||||
$config->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->with('session')
|
||||
->willReturnOnConsecutiveCalls(
|
||||
['driver' => 'native', 'name' => 'session'],
|
||||
['driver' => 'pdo', 'name' => 'foobar']
|
||||
);
|
||||
|
||||
$this->setExpects($app, 'bind', [StorageInterface::class, 'session.storage'], null, $this->atLeastOnce());
|
||||
$this->setExpects($app, 'get', ['request'], $request, $this->atLeastOnce());
|
||||
$this->setExpects($request, 'setSession', [$session], null, $this->atLeastOnce());
|
||||
$this->setExpects($session, 'start', null, null, $this->atLeastOnce());
|
||||
|
||||
$serviceProvider->register();
|
||||
$serviceProvider->register();
|
||||
$serviceProvider->register();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
namespace Engelsystem\Test\Unit\Models;
|
||||
|
||||
use Engelsystem\Test\Unit\Models\Stub\BaseModelImplementation;
|
||||
use Illuminate\Database\Eloquent\Builder as QueryBuilder;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class BaseModelTest extends TestCase
|
||||
|
@ -19,4 +21,26 @@ class BaseModelTest extends TestCase
|
|||
$this->assertEquals('bar', $newModel->foo);
|
||||
$this->assertEquals(1, $newModel->saveCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Models\BaseModel::find
|
||||
*/
|
||||
public function testFind()
|
||||
{
|
||||
/** @var QueryBuilder|MockObject $queryBuilder */
|
||||
$queryBuilder = $this->createMock(QueryBuilder::class);
|
||||
BaseModelImplementation::$queryBuilder = $queryBuilder;
|
||||
|
||||
$anotherModel = new BaseModelImplementation();
|
||||
|
||||
$queryBuilder->expects($this->once())
|
||||
->method('find')
|
||||
->with(1337, ['foo', 'bar'])
|
||||
->willReturn($anotherModel);
|
||||
|
||||
$model = new BaseModelImplementation();
|
||||
$newModel = $model->find(1337, ['foo', 'bar']);
|
||||
|
||||
$this->assertEquals($anotherModel, $newModel);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Engelsystem\Test\Unit\Models\Stub;
|
||||
|
||||
use Engelsystem\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Builder as QueryBuilder;
|
||||
|
||||
/**
|
||||
* @property string foo
|
||||
|
@ -15,6 +16,9 @@ class BaseModelImplementation extends BaseModel
|
|||
/** @var int */
|
||||
public $saveCount = 0;
|
||||
|
||||
/** @var QueryBuilder */
|
||||
public static $queryBuilder = null;
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
* @return bool
|
||||
|
@ -24,4 +28,12 @@ class BaseModelImplementation extends BaseModel
|
|||
$this->saveCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public static function query()
|
||||
{
|
||||
return self::$queryBuilder;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue