Session: Added Symfony PDO backend
This commit is contained in:
parent
edeab5e75f
commit
104e4f4c43
|
@ -137,4 +137,13 @@ return [
|
||||||
'3XL' => '3XL',
|
'3XL' => '3XL',
|
||||||
'4XL' => '4XL'
|
'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->bootEloquent();
|
||||||
$capsule->getConnection()->useDefaultSchemaGrammar();
|
$capsule->getConnection()->useDefaultSchemaGrammar();
|
||||||
|
|
||||||
|
$pdo = null;
|
||||||
try {
|
try {
|
||||||
$capsule->getConnection()->getPdo();
|
$pdo = $capsule->getConnection()->getPdo();
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
$this->exitOnError();
|
$this->exitOnError();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
namespace Engelsystem\Http;
|
namespace Engelsystem\Http;
|
||||||
|
|
||||||
|
use Engelsystem\Config\Config;
|
||||||
use Engelsystem\Container\ServiceProvider;
|
use Engelsystem\Container\ServiceProvider;
|
||||||
use Symfony\Component\HttpFoundation\Session\Session;
|
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\MockArraySessionStorage;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
|
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(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;
|
namespace Engelsystem\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
abstract class BaseModel extends Model
|
abstract class BaseModel extends Model
|
||||||
|
@ -10,6 +12,8 @@ abstract class BaseModel extends Model
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Create a new model
|
||||||
|
*
|
||||||
* @param array $attributes
|
* @param array $attributes
|
||||||
* @return BaseModel
|
* @return BaseModel
|
||||||
*/
|
*/
|
||||||
|
@ -20,4 +24,16 @@ abstract class BaseModel extends Model
|
||||||
|
|
||||||
return $instance;
|
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;
|
namespace Engelsystem\Test\Unit\Database;
|
||||||
|
|
||||||
|
use Engelsystem\Application;
|
||||||
use Engelsystem\Config\Config;
|
use Engelsystem\Config\Config;
|
||||||
use Engelsystem\Database\Database;
|
use Engelsystem\Database\Database;
|
||||||
use Engelsystem\Database\DatabaseServiceProvider;
|
use Engelsystem\Database\DatabaseServiceProvider;
|
||||||
|
@ -10,6 +11,7 @@ use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Database\Capsule\Manager as CapsuleManager;
|
use Illuminate\Database\Capsule\Manager as CapsuleManager;
|
||||||
use Illuminate\Database\Connection;
|
use Illuminate\Database\Connection;
|
||||||
|
use PDO;
|
||||||
use PDOException;
|
use PDOException;
|
||||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||||
|
|
||||||
|
@ -117,12 +119,12 @@ class DatabaseServiceProviderTest extends ServiceProviderTest
|
||||||
$this->setExpects($connection, 'useDefaultSchemaGrammar');
|
$this->setExpects($connection, 'useDefaultSchemaGrammar');
|
||||||
$connection->expects($this->once())
|
$connection->expects($this->once())
|
||||||
->method('getPdo')
|
->method('getPdo')
|
||||||
->willReturnCallback(function () use ($getPdoThrowException) {
|
->willReturnCallback(function () use ($getPdoThrowException, $pdo) {
|
||||||
if ($getPdoThrowException) {
|
if ($getPdoThrowException) {
|
||||||
throw new PDOException();
|
throw new PDOException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return $pdo;
|
||||||
});
|
});
|
||||||
$this->setExpects($dbManager, 'getConnection', [], $connection, $this->atLeastOnce());
|
$this->setExpects($dbManager, 'getConnection', [], $connection, $this->atLeastOnce());
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,14 @@
|
||||||
|
|
||||||
namespace Engelsystem\Test\Unit\Http;
|
namespace Engelsystem\Test\Unit\Http;
|
||||||
|
|
||||||
|
use Engelsystem\Config\Config;
|
||||||
use Engelsystem\Http\Request;
|
use Engelsystem\Http\Request;
|
||||||
use Engelsystem\Http\SessionServiceProvider;
|
use Engelsystem\Http\SessionServiceProvider;
|
||||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||||
|
use PDO;
|
||||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||||
use Symfony\Component\HttpFoundation\Session\Session;
|
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\MockArraySessionStorage;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
|
||||||
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface as StorageInterface;
|
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface as StorageInterface;
|
||||||
|
@ -23,6 +26,9 @@ class SessionServiceProviderTest extends ServiceProviderTest
|
||||||
|
|
||||||
$sessionStorage = $this->getMockForAbstractClass(StorageInterface::class);
|
$sessionStorage = $this->getMockForAbstractClass(StorageInterface::class);
|
||||||
$sessionStorage2 = $this->getMockForAbstractClass(StorageInterface::class);
|
$sessionStorage2 = $this->getMockForAbstractClass(StorageInterface::class);
|
||||||
|
$pdoSessionHandler = $this->getMockBuilder(PdoSessionHandler::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
|
||||||
$session = $this->getSessionMock();
|
$session = $this->getSessionMock();
|
||||||
$request = $this->getRequestMock();
|
$request = $this->getRequestMock();
|
||||||
|
@ -32,22 +38,54 @@ class SessionServiceProviderTest extends ServiceProviderTest
|
||||||
->setConstructorArgs([$app])
|
->setConstructorArgs([$app])
|
||||||
->setMethods(['isCli'])
|
->setMethods(['isCli'])
|
||||||
->getMock();
|
->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')
|
->method('make')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[MockArraySessionStorage::class],
|
[MockArraySessionStorage::class],
|
||||||
[Session::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]
|
[Session::class]
|
||||||
)
|
)
|
||||||
->willReturnOnConsecutiveCalls(
|
->willReturnOnConsecutiveCalls(
|
||||||
$sessionStorage,
|
$sessionStorage,
|
||||||
$session,
|
$session,
|
||||||
$sessionStorage2,
|
$sessionStorage2,
|
||||||
|
$session,
|
||||||
|
$pdoSessionHandler,
|
||||||
|
$sessionStorage2,
|
||||||
$session
|
$session
|
||||||
);
|
);
|
||||||
$app->expects($this->atLeastOnce())
|
$app->expects($this->atLeastOnce())
|
||||||
|
@ -58,13 +96,40 @@ class SessionServiceProviderTest extends ServiceProviderTest
|
||||||
['session', $session]
|
['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, '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($request, 'setSession', [$session], null, $this->atLeastOnce());
|
||||||
$this->setExpects($session, 'start', null, null, $this->atLeastOnce());
|
$this->setExpects($session, 'start', null, null, $this->atLeastOnce());
|
||||||
|
|
||||||
$serviceProvider->register();
|
$serviceProvider->register();
|
||||||
$serviceProvider->register();
|
$serviceProvider->register();
|
||||||
|
$serviceProvider->register();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
namespace Engelsystem\Test\Unit\Models;
|
namespace Engelsystem\Test\Unit\Models;
|
||||||
|
|
||||||
use Engelsystem\Test\Unit\Models\Stub\BaseModelImplementation;
|
use Engelsystem\Test\Unit\Models\Stub\BaseModelImplementation;
|
||||||
|
use Illuminate\Database\Eloquent\Builder as QueryBuilder;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class BaseModelTest extends TestCase
|
class BaseModelTest extends TestCase
|
||||||
|
@ -19,4 +21,26 @@ class BaseModelTest extends TestCase
|
||||||
$this->assertEquals('bar', $newModel->foo);
|
$this->assertEquals('bar', $newModel->foo);
|
||||||
$this->assertEquals(1, $newModel->saveCount);
|
$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;
|
namespace Engelsystem\Test\Unit\Models\Stub;
|
||||||
|
|
||||||
use Engelsystem\Models\BaseModel;
|
use Engelsystem\Models\BaseModel;
|
||||||
|
use Illuminate\Database\Eloquent\Builder as QueryBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property string foo
|
* @property string foo
|
||||||
|
@ -15,6 +16,9 @@ class BaseModelImplementation extends BaseModel
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $saveCount = 0;
|
public $saveCount = 0;
|
||||||
|
|
||||||
|
/** @var QueryBuilder */
|
||||||
|
public static $queryBuilder = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @return bool
|
* @return bool
|
||||||
|
@ -24,4 +28,12 @@ class BaseModelImplementation extends BaseModel
|
||||||
$this->saveCount++;
|
$this->saveCount++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return QueryBuilder
|
||||||
|
*/
|
||||||
|
public static function query()
|
||||||
|
{
|
||||||
|
return self::$queryBuilder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue