From edeab5e75ffa02b075c151ca03ea1038f61e4396 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sun, 16 Sep 2018 00:58:25 +0200 Subject: [PATCH] Added Database class as a replacement for Db, fixed naming --- src/Database/Database.php | 98 ++++++++++++ src/Database/DatabaseServiceProvider.php | 13 +- src/Database/Db.php | 1 + src/Database/Migration/Migrate.php | 14 +- .../Migration/MigrationServiceProvider.php | 11 +- .../Database/DatabaseServiceProviderTest.php | 48 +++++- tests/Unit/Database/DatabaseTest.php | 146 ++++++++++++++++++ tests/Unit/Database/Migration/MigrateTest.php | 14 +- .../MigrationServiceProviderTest.php | 17 +- 9 files changed, 330 insertions(+), 32 deletions(-) create mode 100644 src/Database/Database.php create mode 100644 tests/Unit/Database/DatabaseTest.php 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 @@ +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..cfdc89e7 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 @@ -36,8 +37,18 @@ class DatabaseServiceProvider extends ServiceProvider $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 f34d1564..30f63494 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..cec8bc4a 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 () { }; } @@ -160,11 +160,11 @@ class Migrate */ protected function initMigration() { - if ($this->scheme->hasTable($this->table)) { + if ($this->schema->hasTable($this->table)) { return; } - $this->scheme->create($this->table, function (Blueprint $table) { + $this->schema->create($this->table, function (Blueprint $table) { $table->increments('id'); $table->string('migration'); }); @@ -177,7 +177,7 @@ class Migrate */ 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/tests/Unit/Database/DatabaseServiceProviderTest.php b/tests/Unit/Database/DatabaseServiceProviderTest.php index 8f7898cd..0f259036 100644 --- a/tests/Unit/Database/DatabaseServiceProviderTest.php +++ b/tests/Unit/Database/DatabaseServiceProviderTest.php @@ -3,7 +3,9 @@ namespace Engelsystem\Test\Unit\Database; use Engelsystem\Config\Config; +use Engelsystem\Database\Database; use Engelsystem\Database\DatabaseServiceProvider; +use Engelsystem\Database\Db; use Engelsystem\Test\Unit\ServiceProviderTest; use Exception; use Illuminate\Database\Capsule\Manager as CapsuleManager; @@ -18,9 +20,29 @@ class DatabaseServiceProviderTest extends ServiceProviderTest */ public function testRegister() { - list($app, $dbManager) = $this->prepare(['driver' => 'sqlite', 'database' => ':memory:']); + /** @var Application|MockObject $app */ + /** @var CapsuleManager|MockObject $dbManager */ + /** @var PDO|MockObject $pdo */ + /** @var Database|MockObject $database */ + /** @var Connection|MockObject $connection */ + list($app, $dbManager, $pdo, $database, $connection) = $this->prepare( + [ + 'driver' => 'sqlite', + 'database' => ':memory:' + ] + ); - $this->setExpects($app, 'instance', ['db', $dbManager]); + $app->expects($this->exactly(7)) + ->method('instance') + ->withConsecutive( + [CapsuleManager::class, $dbManager], + [Db::class, $dbManager], + [Connection::class, $connection], + [Database::class, $database], + ['db', $database], + ['db.pdo', $pdo], + ['db.connection', $connection] + ); $serviceProvider = new DatabaseServiceProvider($app); $serviceProvider->register(); @@ -64,13 +86,31 @@ class DatabaseServiceProviderTest extends ServiceProviderTest $connection = $this->getMockBuilder(Connection::class) ->disableOriginalConstructor() ->getMock(); + /** @var PDO|MockObject $pdo */ + $pdo = $this->getMockBuilder(PDO::class) + ->disableOriginalConstructor() + ->getMock(); + /** @var Database|MockObject $database */ + $database = $this->getMockBuilder(Database::class) + ->disableOriginalConstructor() + ->getMock(); $app = $this->getApp(['get', 'make', 'instance']); $this->setExpects($app, 'get', ['config'], $config); - $this->setExpects($app, 'make', [CapsuleManager::class], $dbManager); $this->setExpects($config, 'get', ['database'], $dbConfigData, $this->atLeastOnce()); + $app->expects($this->atLeastOnce()) + ->method('make') + ->withConsecutive( + [CapsuleManager::class], + [Database::class] + ) + ->willReturn( + $dbManager, + $database + ); + $this->setExpects($dbManager, 'setAsGlobal'); $this->setExpects($dbManager, 'bootEloquent'); @@ -86,6 +126,6 @@ class DatabaseServiceProviderTest extends ServiceProviderTest }); $this->setExpects($dbManager, 'getConnection', [], $connection, $this->atLeastOnce()); - return [$app, $dbManager]; + return [$app, $dbManager, $pdo, $database, $connection]; } } diff --git a/tests/Unit/Database/DatabaseTest.php b/tests/Unit/Database/DatabaseTest.php new file mode 100644 index 00000000..91d6a6c7 --- /dev/null +++ b/tests/Unit/Database/DatabaseTest.php @@ -0,0 +1,146 @@ +getMockBuilder(Pdo::class) + ->disableOriginalConstructor() + ->getMock(); + + /** @var DatabaseConnection|MockObject $databaseConnection */ + $databaseConnection = $this->getMockBuilder(DatabaseConnection::class) + ->disableOriginalConstructor() + ->getMock(); + $databaseConnection->expects($this->atLeastOnce()) + ->method('getPdo') + ->willReturn($pdo); + + $db = new Database($databaseConnection); + + $this->assertEquals($databaseConnection, $db->getConnection()); + $this->assertEquals($pdo, $db->getPdo()); + $this->assertInstanceOf(PDO::class, $db->getPdo()); + } + + /** + * @covers \Engelsystem\Database\Database::select() + */ + public function testSelect() + { + $db = new Database($this->connection); + + $return = $db->select('SELECT * FROM test_data'); + $this->assertTrue(count($return) > 3); + + $return = $db->select('SELECT * FROM test_data WHERE id = ?', [2]); + $this->assertCount(1, $return); + } + + /** + * @covers \Engelsystem\Database\Database::selectOne() + */ + public function testSelectOne() + { + $db = new Database($this->connection); + + $return = $db->selectOne('SELECT * FROM test_data'); + $this->assertEquals('Foo', $return->data); + + $return = $db->selectOne('SELECT * FROM test_data WHERE id = -1'); + $this->assertEmpty($return); + + $return = $db->selectOne('SELECT * FROM test_data WHERE id = ?', [3]); + $this->assertTrue(!is_array($return)); + } + + /** + * @covers \Engelsystem\Database\Database::insert() + */ + public function testInsert() + { + $db = new Database($this->connection); + + $result = $db->insert("INSERT INTO test_data (id, data) VALUES (5, 'Some random text'), (6, 'another text')"); + $this->assertTrue($result); + } + + /** + * @covers \Engelsystem\Database\Database::update() + */ + public function testUpdate() + { + $db = new Database($this->connection); + + $count = $db->update("UPDATE test_data SET data='NOPE' WHERE data LIKE '%Replaceme%'"); + $this->assertEquals(3, $count); + + $count = $db->update("UPDATE test_data SET data=? WHERE data LIKE '%NOPE%'", ['Some random text!']); + $this->assertEquals(3, $count); + } + + /** + * @covers \Engelsystem\Database\Database::delete() + */ + public function testDelete() + { + $db = new Database($this->connection); + + $count = $db->delete('DELETE FROM test_data WHERE id=1'); + $this->assertEquals(1, $count); + + $count = $db->delete('DELETE FROM test_data WHERE data LIKE ?', ['%Replaceme%']); + $this->assertEquals(3, $count); + } + + /** + * Setup in memory database + */ + protected function setUp() + { + $dbManager = new CapsuleManager(); + $dbManager->addConnection(['driver' => 'sqlite', 'database' => ':memory:']); + + $connection = $dbManager->getConnection(); + $this->connection = $connection; + + $connection->getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $connection->statement( + ' + CREATE TABLE test_data( + id INT PRIMARY KEY NOT NULL, + data TEXT NOT NULL + ); + '); + $connection->statement('CREATE UNIQUE INDEX test_data_id_uindex ON test_data (id);'); + $connection->insert(" + INSERT INTO test_data (id, data) + VALUES + (1, 'Foo'), + (2, 'Bar'), + (3, 'Batz'), + (4, 'Lorem ipsum dolor sit'), + (10, 'Replaceme ipsum dolor sit amet'), + (11, 'Lorem Replaceme dolor sit amet'), + (12, 'Lorem ipsum Replaceme sit amet') + ;"); + } +} diff --git a/tests/Unit/Database/Migration/MigrateTest.php b/tests/Unit/Database/Migration/MigrateTest.php index c88ad777..2adbed41 100644 --- a/tests/Unit/Database/Migration/MigrateTest.php +++ b/tests/Unit/Database/Migration/MigrateTest.php @@ -120,12 +120,12 @@ class MigrateTest extends TestCase $dbManager->bootEloquent(); $db = $dbManager->getConnection(); $db->useDefaultSchemaGrammar(); - $scheme = $db->getSchemaBuilder(); + $schema = $db->getSchemaBuilder(); - $app->instance('scheme', $scheme); - $app->bind(SchemaBuilder::class, 'scheme'); + $app->instance('schema', $schema); + $app->bind(SchemaBuilder::class, 'schema'); - $migration = new Migrate($scheme, $app); + $migration = new Migrate($schema, $app); $messages = []; $migration->setOutput(function ($msg) use (&$messages) { @@ -134,7 +134,7 @@ class MigrateTest extends TestCase $migration->run(__DIR__ . '/Stub', Migrate::UP); - $this->assertTrue($scheme->hasTable('migrations')); + $this->assertTrue($schema->hasTable('migrations')); $migrations = $db->table('migrations')->get(); $this->assertCount(3, $migrations); @@ -143,7 +143,7 @@ class MigrateTest extends TestCase $this->assertTrue($migrations->contains('migration', '2017_12_24_053300_another_stuff')); $this->assertTrue($migrations->contains('migration', '2022_12_22_221222_add_some_feature')); - $this->assertTrue($scheme->hasTable('lorem_ipsum')); + $this->assertTrue($schema->hasTable('lorem_ipsum')); $migration->run(__DIR__ . '/Stub', Migrate::DOWN, true); @@ -155,6 +155,6 @@ class MigrateTest extends TestCase $migrations = $db->table('migrations')->get(); $this->assertCount(0, $migrations); - $this->assertFalse($scheme->hasTable('lorem_ipsum')); + $this->assertFalse($schema->hasTable('lorem_ipsum')); } } diff --git a/tests/Unit/Database/Migration/MigrationServiceProviderTest.php b/tests/Unit/Database/Migration/MigrationServiceProviderTest.php index a99cdebe..593da5c5 100644 --- a/tests/Unit/Database/Migration/MigrationServiceProviderTest.php +++ b/tests/Unit/Database/Migration/MigrationServiceProviderTest.php @@ -2,11 +2,10 @@ namespace Engelsystem\Test\Unit\Database\Migration; -use Engelsystem\Database\Db; +use Engelsystem\Database\Database; use Engelsystem\Database\Migration\Migrate; use Engelsystem\Database\Migration\MigrationServiceProvider; use Engelsystem\Test\Unit\ServiceProviderTest; -use Illuminate\Database\Capsule\Manager as CapsuleManager; use Illuminate\Database\Connection; use Illuminate\Database\Schema\Builder as SchemaBuilder; use PHPUnit_Framework_MockObject_MockObject as MockObject; @@ -22,8 +21,8 @@ class MigrationServiceProviderTest extends ServiceProviderTest $migration = $this->getMockBuilder(Migrate::class) ->disableOriginalConstructor() ->getMock(); - /** @var MockObject|CapsuleManager $dbManager */ - $dbManager = $this->getMockBuilder(CapsuleManager::class) + /** @var Database|MockObject $database */ + $database = $this->getMockBuilder(Database::class) ->disableOriginalConstructor() ->getMock(); /** @var MockObject|Connection $dbConnection */ @@ -35,19 +34,19 @@ class MigrationServiceProviderTest extends ServiceProviderTest ->disableOriginalConstructor() ->getMock(); - $app = $this->getApp(['make', 'instance', 'bind']); + $app = $this->getApp(['make', 'instance', 'bind', 'get']); $app->expects($this->atLeastOnce()) ->method('instance') - ->withConsecutive(['db.scheme'], ['db.migration']) + ->withConsecutive(['db.schema'], ['db.migration']) ->willReturnOnConsecutiveCalls($schemaBuilder, $migration); - $this->setExpects($app, 'bind', [SchemaBuilder::class, 'db.scheme']); + $this->setExpects($app, 'bind', [SchemaBuilder::class, 'db.schema']); $this->setExpects($app, 'make', [Migrate::class], $migration); + $this->setExpects($app, 'get', [Database::class], $database); $this->setExpects($dbConnection, 'getSchemaBuilder', null, $schemaBuilder); - $this->setExpects($dbManager, 'getConnection', null, $dbConnection); - Db::setDbManager($dbManager); + $this->setExpects($database, 'getConnection', null, $dbConnection); $serviceProvider = new MigrationServiceProvider($app); $serviceProvider->register();