From b1af1f9cc2497087e5de47970024c235a17ea4c2 Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Tue, 15 Aug 2017 23:05:43 +0200 Subject: [PATCH 01/20] Change default value for datetime fields to valid range --- db/install.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/install.sql b/db/install.sql index 0222dc08..3c3e41e6 100644 --- a/db/install.sql +++ b/db/install.sql @@ -205,7 +205,7 @@ DROP TABLE IF EXISTS `NewsComments`; CREATE TABLE `NewsComments` ( `ID` bigint(11) NOT NULL, `Refid` int(11) NOT NULL DEFAULT '0', - `Datum` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `Datum` datetime NOT NULL DEFAULT '1000-01-01 00:00:00', `Text` text NOT NULL, `UID` int(11) NOT NULL DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -395,7 +395,7 @@ CREATE TABLE `User` ( `Sprache` char(64) NOT NULL, `Menu` char(1) NOT NULL DEFAULT 'L', `lastLogIn` int(11) NOT NULL, - `CreateDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `CreateDate` datetime NOT NULL DEFAULT '1000-01-01 00:00:00', `Art` varchar(30) DEFAULT NULL, `kommentar` text, `Hometown` varchar(255) NOT NULL DEFAULT '', From dc6fb49f44c12e2bc354d7355d5cd903017568e9 Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Wed, 16 Aug 2017 00:19:16 +0200 Subject: [PATCH 02/20] fix only_full_group_by mysql default behaviour --- includes/model/UserAngelTypes_model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/model/UserAngelTypes_model.php b/includes/model/UserAngelTypes_model.php index 11366cdf..410a292f 100644 --- a/includes/model/UserAngelTypes_model.php +++ b/includes/model/UserAngelTypes_model.php @@ -59,7 +59,7 @@ function User_unconfirmed_AngelTypes($user) { AND `UserAngelTypes`.`supporter`=TRUE AND `AngelTypes`.`restricted`=TRUE AND `UnconfirmedMembers`.`confirm_user_id` IS NULL - GROUP BY `UserAngelTypes`.`angeltype_id` + GROUP BY `UserAngelTypes`.`angeltype_id`, `UserAngelTypes`.`id` ORDER BY `AngelTypes`.`name`"); if ($result === false) { engelsystem_error("Unable to load user angeltypes."); From 5f305121a4fb6a21bedcd82d845909aed38cec0c Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Wed, 16 Aug 2017 00:45:56 +0200 Subject: [PATCH 03/20] fix order by not in select clause for >mysql-5.7 --- includes/pages/user_shifts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/pages/user_shifts.php b/includes/pages/user_shifts.php index c990ee4a..30f129c7 100644 --- a/includes/pages/user_shifts.php +++ b/includes/pages/user_shifts.php @@ -89,7 +89,7 @@ function load_days() { $days = sql_select_single_col(" SELECT DISTINCT DATE(FROM_UNIXTIME(`start`)) AS `id`, DATE(FROM_UNIXTIME(`start`)) AS `name` FROM `Shifts` - ORDER BY `start`"); + ORDER BY `id`, `name`"); if (count($days) == 0) { error(_("The administration has not configured any shifts yet.")); redirect('?'); From eeae07e625890cee9a3cb90ee87e07530b7bf192 Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Wed, 16 Aug 2017 01:31:53 +0200 Subject: [PATCH 04/20] add edited_at_timestamp to shift creation to fix mysql error --- includes/model/Shifts_model.php | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/model/Shifts_model.php b/includes/model/Shifts_model.php index 29156423..baaf4c28 100644 --- a/includes/model/Shifts_model.php +++ b/includes/model/Shifts_model.php @@ -334,6 +334,7 @@ function Shift_create($shift) { `URL`=" . sql_null($shift['URL']) . ", `PSID`=" . sql_null($shift['PSID']) . ", `created_by_user_id`='" . sql_escape($user['UID']) . "', + `edited_at_timestamp`=" . time() .", `created_at_timestamp`=" . time()); if ($result === false) { return false; From 212760d4c93ce14e9ae34ef207bbb8f48a7dd9a7 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Thu, 21 Sep 2017 18:37:37 +0200 Subject: [PATCH 05/20] Changed Container to Illuminate/Container @see https://laravel.com/docs/5.5/container @see https://davejamesmiller.com/2017/06/15/laravel-illuminate-container-in-depth --- composer.json | 9 +- includes/engelsystem_provider.php | 4 +- src/Application.php | 4 +- src/Container/Container.php | 110 +------------------------ src/Container/ContainerException.php | 11 --- src/Container/NotFoundException.php | 10 --- tests/Unit/ApplicationTest.php | 1 + tests/Unit/Container/ContainerTest.php | 104 ----------------------- 8 files changed, 12 insertions(+), 241 deletions(-) delete mode 100644 src/Container/ContainerException.php delete mode 100644 src/Container/NotFoundException.php delete mode 100644 tests/Unit/Container/ContainerTest.php diff --git a/composer.json b/composer.json index 35956e20..6467fc1c 100644 --- a/composer.json +++ b/composer.json @@ -15,11 +15,12 @@ ], "require": { "php": ">=7.0.0", - "erusev/parsedown": "1.6.*", - "twbs/bootstrap": "^3.3", - "symfony/http-foundation": "^3.3", + "erusev/parsedown": "^1.6", + "illuminate/container": "^5.*", "psr/container": "^1.0", - "psr/log": "^1.0" + "psr/log": "^1.0", + "symfony/http-foundation": "^3.3", + "twbs/bootstrap": "^3.3" }, "require-dev": { "phpunit/phpunit": "^6.3" diff --git a/includes/engelsystem_provider.php b/includes/engelsystem_provider.php index 0de5e0f5..33422bfc 100644 --- a/includes/engelsystem_provider.php +++ b/includes/engelsystem_provider.php @@ -106,8 +106,8 @@ Db::getPdo()->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); */ $logger = new EngelsystemLogger(); $app->instance('logger', $logger); -$app->instance(LoggerInterface::class, $logger); -$app->instance(EngelsystemLogger::class, $logger); +$app->bind(LoggerInterface::class, 'logger'); +$app->bind(EngelsystemLogger::class, 'logger'); /** diff --git a/src/Application.php b/src/Application.php index 674b3869..fa895d77 100644 --- a/src/Application.php +++ b/src/Application.php @@ -14,12 +14,12 @@ class Application extends Container protected function registerBaseBindings() { - self::setInstance($this); + static::setInstance($this); Container::setInstance($this); $this->instance('app', $this); $this->instance('container', $this); $this->instance(Container::class, $this); $this->instance(Application::class, $this); - $this->instance(ContainerInterface::class, $this); + $this->bind(ContainerInterface::class, Application::class); } } diff --git a/src/Container/Container.php b/src/Container/Container.php index 59a17a04..44c57b6f 100644 --- a/src/Container/Container.php +++ b/src/Container/Container.php @@ -2,115 +2,9 @@ namespace Engelsystem\Container; -use Psr\Container\ContainerExceptionInterface; +use Illuminate\Container\Container as IlluminateContainer; use Psr\Container\ContainerInterface; -use Psr\Container\NotFoundExceptionInterface; -class Container implements ContainerInterface +class Container extends IlluminateContainer implements ContainerInterface { - /** - * The globally available container - * - * @var static - */ - protected static $instance; - - /** - * Contains the shared instances - * - * @var mixed[] - */ - protected $instances = []; - - /** - * Finds an entry of the container by its identifier and returns it - * - * @param string $id Identifier of the entry to look for - * - * @throws NotFoundExceptionInterface No entry was found for **this** identifier - * @throws ContainerExceptionInterface Error while retrieving the entry - * - * @return mixed Entry - */ - public function get($id) - { - if ($this->has($id)) { - return $this->resolve($id); - } - - throw new NotFoundException(sprintf('The entry with the id "%s" could not be found', $id)); - } - - /** - * Register a shared entry in the container - * - * @param string $abstract Identifier of the entry to set - * @param mixed $instance Entry - */ - public function instance($abstract, $instance) - { - $this->singleton($abstract, $instance); - } - - /** - * Register a shared entry as singleton in the container - * - * @param string $abstract - * @param mixed $instance - */ - public function singleton($abstract, $instance) - { - $this->instances[$abstract] = $instance; - } - - /** - * Returns true if the container can return an entry for the given identifier - * Returns false otherwise - * - * `has($id)` returning true does not mean that `get($id)` will not throw an exception - * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface` - * - * @param string $id Identifier of the entry to look for - * - * @return bool - */ - public function has($id) - { - return isset($this->instances[$id]); - } - - /** - * Resolve the requested object - * - * @param string $abstract - * @return mixed - */ - protected function resolve($abstract) - { - return $this->instances[$abstract]; - } - - /** - * Get the globally available instance of the container - * - * @return self - */ - public static function getInstance() - { - if (is_null(static::$instance)) { - static::$instance = new static; - } - - return static::$instance; - } - - /** - * Set the globally available instance of the container - * - * @param Container $container - */ - public static function setInstance(Container $container) - { - static::$instance = $container; - } } diff --git a/src/Container/ContainerException.php b/src/Container/ContainerException.php deleted file mode 100644 index 3cdde506..00000000 --- a/src/Container/ContainerException.php +++ /dev/null @@ -1,11 +0,0 @@ -assertSame($app, $app->get(Container::class)); $this->assertSame($app, $app->get(Application::class)); $this->assertSame($app, $app->get(ContainerInterface::class)); + $this->assertSame($app, Application::getInstance()); $this->assertSame($app, Container::getInstance()); } } diff --git a/tests/Unit/Container/ContainerTest.php b/tests/Unit/Container/ContainerTest.php deleted file mode 100644 index 89c34209..00000000 --- a/tests/Unit/Container/ContainerTest.php +++ /dev/null @@ -1,104 +0,0 @@ -instance('foo', $class); - $this->assertSame($class, $container->get('foo')); - } - - /** - * @covers \Engelsystem\Container\Container::get - * @expectedException \Engelsystem\Container\NotFoundException - */ - public function testGetException() - { - $container = new Container(); - - $container->get('not.registered.service'); - } - - /** - * @covers \Engelsystem\Container\Container::instance - * @covers \Engelsystem\Container\Container::resolve - */ - public function testInstance() - { - $container = new Container(); - $class = new class - { - }; - - $container->instance('foo', $class); - $this->assertSame($class, $container->get('foo')); - } - - /** - * @covers \Engelsystem\Container\Container::has - */ - public function testHas() - { - $container = new Container(); - - $this->assertFalse($container->has('test')); - - $class = new class - { - }; - - $container->instance('test', $class); - $this->assertTrue($container->has('test')); - } - - /** - * @covers \Engelsystem\Container\Container::singleton - */ - public function testSingleton() - { - $container = new Container(); - $class = new class - { - }; - - $container->singleton('foo', $class); - $this->assertSame($class, $container->get('foo')); - $this->assertSame($class, $container->get('foo')); - } - - /** - * @covers \Engelsystem\Container\Container::setInstance - * @covers \Engelsystem\Container\Container::getInstance - */ - public function testContainerSingleton() - { - // Ensure that no container has been initialized - $reflection = new \ReflectionProperty(Container::class, 'instance'); - $reflection->setAccessible(true); - $reflection->setValue(null, null); - $reflection->setAccessible(false); - - $container0 = new Container(); - $container = Container::getInstance(); - - $this->assertNotSame($container0, $container); - - $container1 = new Container; - Container::setInstance($container1); - - $this->assertSame($container1, Container::getInstance()); - } -} From 783c58611ada88460ba670d51ebf4013563e1197 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Thu, 21 Sep 2017 20:52:19 +0200 Subject: [PATCH 06/20] Added app path to container --- includes/engelsystem_provider.php | 2 +- src/Application.php | 36 ++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/includes/engelsystem_provider.php b/includes/engelsystem_provider.php index 33422bfc..e1669c57 100644 --- a/includes/engelsystem_provider.php +++ b/includes/engelsystem_provider.php @@ -23,7 +23,7 @@ require_once __DIR__ . '/autoload.php'; /** * Initialize the application */ -$app = Application::getInstance(); +$app = new Application(realpath(__DIR__ . DIRECTORY_SEPARATOR . '..')); /** diff --git a/src/Application.php b/src/Application.php index fa895d77..80538396 100644 --- a/src/Application.php +++ b/src/Application.php @@ -7,8 +7,20 @@ use Psr\Container\ContainerInterface; class Application extends Container { - public function __construct() + /** @var string|null */ + protected $appPath = null; + + /** + * Application constructor. + * + * @param string $appPath + */ + public function __construct($appPath = null) { + if (!is_null($appPath)) { + $this->setAppPath($appPath); + } + $this->registerBaseBindings(); } @@ -22,4 +34,26 @@ class Application extends Container $this->instance(Application::class, $this); $this->bind(ContainerInterface::class, Application::class); } + + /** + * @param string $appPath + * @return static + */ + public function setAppPath($appPath) + { + $appPath = rtrim($appPath, DIRECTORY_SEPARATOR); + + $this->appPath = $appPath; + $this->instance('path', $appPath); + + return $this; + } + + /** + * @return string|null + */ + public function path() + { + return $this->appPath; + } } From d49e49c364c1b73e4e4e3b52dc10ee9d0150e447 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Fri, 22 Sep 2017 14:02:02 +0200 Subject: [PATCH 07/20] Implemented service provider functionality --- config/app.php | 9 ++ includes/engelsystem_provider.php | 13 +- .../helper/internationalization_helper.php | 2 +- src/Application.php | 80 +++++++++- src/Container/ServiceProvider.php | 31 ++++ src/helpers.php | 50 ++++-- tests/Unit/ApplicationTest.php | 147 +++++++++++++++++- 7 files changed, 310 insertions(+), 22 deletions(-) create mode 100644 config/app.php create mode 100644 src/Container/ServiceProvider.php diff --git a/config/app.php b/config/app.php new file mode 100644 index 00000000..fe0a97c1 --- /dev/null +++ b/config/app.php @@ -0,0 +1,9 @@ + [ + ], +]; diff --git a/includes/engelsystem_provider.php b/includes/engelsystem_provider.php index e1669c57..3067ab62 100644 --- a/includes/engelsystem_provider.php +++ b/includes/engelsystem_provider.php @@ -26,6 +26,13 @@ require_once __DIR__ . '/autoload.php'; $app = new Application(realpath(__DIR__ . DIRECTORY_SEPARATOR . '..')); +/** + * Bootstrap application + */ +$appConfig = $app->make(Config::class); +$appConfig->set(app('path.config') . '/app.php'); +$app->bootstrap($appConfig); + /** * Load configuration */ @@ -40,6 +47,10 @@ if (file_exists(__DIR__ . '/../config/config.php')) { )); } + +/** + * Configure application + */ date_default_timezone_set($config->get('timezone')); @@ -55,7 +66,7 @@ $app->instance('request', $request); /** * Check for maintenance */ -if ($config->get('maintenance')) { +if ($app->get('config')->get('maintenance')) { echo file_get_contents(__DIR__ . '/../templates/maintenance.html'); die(); } diff --git a/includes/helper/internationalization_helper.php b/includes/helper/internationalization_helper.php index efbe5db5..7fa6518b 100644 --- a/includes/helper/internationalization_helper.php +++ b/includes/helper/internationalization_helper.php @@ -36,7 +36,7 @@ function gettext_init() } gettext_locale(); - bindtextdomain('default', realpath(__DIR__ . '/../../locale')); + bindtextdomain('default', app('path.lang')); bind_textdomain_codeset('default', 'UTF-8'); textdomain('default'); } diff --git a/src/Application.php b/src/Application.php index 80538396..b62b28a9 100644 --- a/src/Application.php +++ b/src/Application.php @@ -2,7 +2,9 @@ namespace Engelsystem; +use Engelsystem\Config\Config; use Engelsystem\Container\Container; +use Engelsystem\Container\ServiceProvider; use Psr\Container\ContainerInterface; class Application extends Container @@ -10,6 +12,16 @@ class Application extends Container /** @var string|null */ protected $appPath = null; + /** @var bool */ + protected $isBootstrapped = false; + + /** + * Registered service providers + * + * @var array + */ + protected $serviceProviders = []; + /** * Application constructor. * @@ -36,15 +48,73 @@ class Application extends Container } /** + * @param string|ServiceProvider $provider + * @return ServiceProvider + */ + public function register($provider) + { + if (is_string($provider)) { + $provider = $this->get($provider); + } + + $this->serviceProviders[] = $provider; + + $provider->register(); + + if ($this->isBootstrapped) { + $this->call([$provider, 'boot']); + } + + return $provider; + } + + /** + * Boot service providers + * + * @param Config|null $config + */ + public function bootstrap(Config $config = null) + { + if ($this->isBootstrapped) { + return; + } + + if ($config instanceof Config) { + foreach ($config->get('providers', []) as $provider) { + $this->register($provider); + } + } + + foreach ($this->serviceProviders as $provider) { + $this->call([$provider, 'boot']); + } + + $this->isBootstrapped = true; + } + + protected function registerPaths() + { + $appPath = $this->appPath; + + $this->instance('path', $appPath); + $this->instance('path.config', $appPath . DIRECTORY_SEPARATOR . 'config'); + $this->instance('path.lang', $appPath . DIRECTORY_SEPARATOR . 'locale'); + } + + /** + * Set app base path + * * @param string $appPath * @return static */ public function setAppPath($appPath) { + $appPath = realpath($appPath); $appPath = rtrim($appPath, DIRECTORY_SEPARATOR); $this->appPath = $appPath; - $this->instance('path', $appPath); + + $this->registerPaths(); return $this; } @@ -56,4 +126,12 @@ class Application extends Container { return $this->appPath; } + + /** + * @return bool + */ + public function isBooted() + { + return $this->isBootstrapped; + } } diff --git a/src/Container/ServiceProvider.php b/src/Container/ServiceProvider.php new file mode 100644 index 00000000..2a1bbebf --- /dev/null +++ b/src/Container/ServiceProvider.php @@ -0,0 +1,31 @@ +app = $app; + } + + /** + * Register container bindings + */ + public function register() { } + + /** + * Called after other services had been registered + */ + public function boot() { } +} diff --git a/src/helpers.php b/src/helpers.php index de303963..c3c727ec 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -23,6 +23,15 @@ function app($id = null) return Application::getInstance()->get($id); } +/** + * @param string $path + * @return string + */ +function base_path($path = '') +{ + return app('path') . (empty($path) ? '' : DIRECTORY_SEPARATOR . $path); +} + /** * Get or set config values * @@ -46,6 +55,15 @@ function config($key = null, $default = null) return $config->get($key, $default); } +/** + * @param string $path + * @return string + */ +function config_path($path = '') +{ + return app('path.config') . (empty($path) ? '' : DIRECTORY_SEPARATOR . $path); +} + /** * @param string $key * @param mixed $default @@ -78,22 +96,6 @@ function session($key = null, $default = null) return $session->get($key, $default); } -/** - * @param string $template - * @param mixed[] $data - * @return Renderer|string - */ -function view($template = null, $data = null) -{ - $renderer = app('renderer'); - - if (is_null($template)) { - return $renderer; - } - - return $renderer->render($template, $data); -} - /** * @param string $path * @param array $parameters @@ -109,3 +111,19 @@ function url($path = null, $parameters = []) return $urlGenerator->to($path, $parameters); } + +/** + * @param string $template + * @param mixed[] $data + * @return Renderer|string + */ +function view($template = null, $data = null) +{ + $renderer = app('renderer'); + + if (is_null($template)) { + return $renderer; + } + + return $renderer->render($template, $data); +} diff --git a/tests/Unit/ApplicationTest.php b/tests/Unit/ApplicationTest.php index 53fe3109..78310134 100644 --- a/tests/Unit/ApplicationTest.php +++ b/tests/Unit/ApplicationTest.php @@ -3,19 +3,23 @@ namespace Engelsystem\Test\Config; use Engelsystem\Application; +use Engelsystem\Config\Config; use Engelsystem\Container\Container; +use Engelsystem\Container\ServiceProvider; use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_MockObject_MockObject; use Psr\Container\ContainerInterface; +use ReflectionClass; class ApplicationTest extends TestCase { /** - * @covers \Engelsystem\Application::__construct - * @covers \Engelsystem\Application::registerBaseBindings + * @covers \Engelsystem\Application::__construct + * @covers \Engelsystem\Application::registerBaseBindings */ public function testConstructor() { - $app = new Application(); + $app = new Application('.'); $this->assertInstanceOf(Container::class, $app); $this->assertInstanceOf(ContainerInterface::class, $app); @@ -27,4 +31,141 @@ class ApplicationTest extends TestCase $this->assertSame($app, Application::getInstance()); $this->assertSame($app, Container::getInstance()); } + + /** + * @covers \Engelsystem\Application::setAppPath + * @covers \Engelsystem\Application::registerPaths + * @covers \Engelsystem\Application::path + */ + public function testAppPath() + { + $app = new Application(); + + $this->assertFalse($app->has('path')); + + $app->setAppPath('.'); + $this->assertTrue($app->has('path')); + $this->assertTrue($app->has('path.config')); + $this->assertTrue($app->has('path.lang')); + + $this->assertEquals(realpath('.'), $app->path()); + $this->assertEquals(realpath('.') . '/config', $app->get('path.config')); + + $app->setAppPath('./../'); + $this->assertEquals(realpath('../') . '/config', $app->get('path.config')); + } + + /** + * @covers \Engelsystem\Application::register + */ + public function testRegister() + { + $app = new Application(); + + $serviceProvider = $this->mockServiceProvider($app, ['register']); + $serviceProvider->expects($this->once()) + ->method('register'); + + $app->register($serviceProvider); + + $anotherServiceProvider = $this->mockServiceProvider($app, ['register', 'boot']); + $anotherServiceProvider->expects($this->once()) + ->method('register'); + $anotherServiceProvider->expects($this->once()) + ->method('boot'); + + $app->bootstrap(); + $app->register($anotherServiceProvider); + } + + /** + * @covers \Engelsystem\Application::register + */ + public function testRegisterBoot() + { + $app = new Application(); + $app->bootstrap(); + + $serviceProvider = $this->mockServiceProvider($app, ['register', 'boot']); + $serviceProvider->expects($this->once()) + ->method('register'); + $serviceProvider->expects($this->once()) + ->method('boot'); + + $app->register($serviceProvider); + } + + /** + * @covers \Engelsystem\Application::register + */ + public function testRegisterClassName() + { + $app = new Application(); + + $mockClassName = $this->getMockClass(ServiceProvider::class); + $serviceProvider = $this->getMockBuilder($mockClassName) + ->setConstructorArgs([$app]) + ->setMethods(['register']) + ->getMock(); + + $serviceProvider->expects($this->once()) + ->method('register'); + + $app->instance($mockClassName, $serviceProvider); + $app->register($mockClassName); + } + + /** + * @covers \Engelsystem\Application::bootstrap + * @covers \Engelsystem\Application::isBooted + */ + public function testBootstrap() + { + /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ + $app = $this->getMockBuilder(Application::class) + ->setMethods(['register']) + ->getMock(); + + $serviceProvider = $this->mockServiceProvider($app, ['boot']); + $serviceProvider->expects($this->once()) + ->method('boot'); + + $app->expects($this->once()) + ->method('register') + ->with($serviceProvider); + + $config = $this->getMockBuilder(Config::class) + ->getMock(); + + $config->expects($this->once()) + ->method('get') + ->with('providers') + ->willReturn([$serviceProvider]); + + $property = (new ReflectionClass($app))->getProperty('serviceProviders'); + $property->setAccessible(true); + $property->setValue($app, [$serviceProvider]); + + $app->bootstrap($config); + + $this->assertTrue($app->isBooted()); + + // Run bootstrap another time to ensure that providers are registered only once + $app->bootstrap($config); + } + + /** + * @param Application $app + * @param array $methods + * @return PHPUnit_Framework_MockObject_MockObject|ServiceProvider + */ + protected function mockServiceProvider(Application $app, $methods = []) + { + $serviceProvider = $this->getMockBuilder(ServiceProvider::class) + ->setConstructorArgs([$app]) + ->setMethods($methods) + ->getMockForAbstractClass(); + + return $serviceProvider; + } } From c5c0a602aab908ed7bac3a87b7a574bef0a5ed8f Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sun, 24 Sep 2017 20:17:17 +0200 Subject: [PATCH 08/20] Fixed composer --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6467fc1c..a8f0b0d6 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "require": { "php": ">=7.0.0", "erusev/parsedown": "^1.6", - "illuminate/container": "^5.*", + "illuminate/container": "5.5.*", "psr/container": "^1.0", "psr/log": "^1.0", "symfony/http-foundation": "^3.3", From 449e2cdd00632acff63bb75c5282c3aa2642b59f Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Mon, 25 Sep 2017 00:03:22 +0200 Subject: [PATCH 09/20] Added env function, added GitLab CI code coverage config --- .gitlab-ci.yml | 47 ++++++++++++++++++++++++++++++++++++++ config/config.default.php | 8 +++---- src/helpers.php | 15 ++++++++++++ tests/Unit/HelpersTest.php | 14 ++++++++++++ 4 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..c44507b1 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,47 @@ +image: php + +cache: + paths: + - .composer + +services: + - mysql:5.6 + +variables: + MYSQL_DATABASE: engelsystem + MYSQL_USER: engel + MYSQL_PASSWORD: engelsystem + COMPOSER_HOME: .composer + MYSQL_RANDOM_ROOT_PASSWORD: "yes" + +before_script: + # Install required Packages + - apt-get update -yqq + - apt-get install -yqq git unzip mysql-client + - docker-php-ext-install pdo pdo_mysql gettext + # Install xdebug + - pecl install xdebug + - docker-php-ext-enable xdebug + # MySQL DB + - mysql -h mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" < db/install.sql + - mysql -h mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" < db/update.sql + # Install Composer + - curl -sS https://getcomposer.org/installer | php -- --no-ansi --install-dir /usr/local/bin/ --filename composer + - /usr/local/bin/composer --no-ansi install + +.test_template: &test_definition + artifacts: + name: "${CI_JOB_NAME}_${CI_PROJECT_ID}_${PHP_VERSION}" + expire_in: 1 week + paths: + - ./coverage/ + coverage: '/^\s*Lines:\s*(\d+(?:\.\d+)?%)/' + script: vendor/bin/phpunit --colors=never --coverage-text --coverage-html ./coverage/ + +test:7.0: + image: php:7.0 + <<: *test_definition + +test:7.1: + image: php:7.1 + <<: *test_definition diff --git a/config/config.default.php b/config/config.default.php index c2d742ef..1bad9668 100644 --- a/config/config.default.php +++ b/config/config.default.php @@ -5,10 +5,10 @@ return [ // MySQL-Connection Settings 'database' => [ - 'host' => 'localhost', - 'user' => 'root', - 'pw' => '', - 'db' => 'engelsystem', + 'host' => env('MYSQL_HOST', (env('CI', false) ? 'mysql' : 'localhost')), + 'user' => env('MYSQL_USER', 'root'), + 'pw' => env('MYSQL_PASSWORD', ''), + 'db' => env('MYSQL_DATABASE', 'engelsystem'), ], // For accessing stats diff --git a/src/helpers.php b/src/helpers.php index c3c727ec..5a48498a 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -64,6 +64,21 @@ function config_path($path = '') return app('path.config') . (empty($path) ? '' : DIRECTORY_SEPARATOR . $path); } +/** + * @param string $key + * @param mixed $default + * @return mixed + */ +function env($key, $default = null) +{ + $value = getenv($key); + if ($value === false) { + return $default; + } + + return $value; +} + /** * @param string $key * @param mixed $default diff --git a/tests/Unit/HelpersTest.php b/tests/Unit/HelpersTest.php index d9782888..9ec824af 100644 --- a/tests/Unit/HelpersTest.php +++ b/tests/Unit/HelpersTest.php @@ -53,6 +53,20 @@ class HelpersTest extends TestCase $this->assertEquals(['user' => 'FooBar'], config('mail')); } + /** + * @covers \env + */ + public function testEnv() + { + putenv('envTestVar=someContent'); + + $env = env('envTestVar'); + $this->assertEquals('someContent', $env); + + $env = env('someRandomEnvVarThatShouldNeverExist', 'someDefaultValue'); + $this->assertEquals('someDefaultValue', $env); + } + /** * @covers \request */ From fb05a38a963784716c105e7f214615ad13d2f272 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sun, 22 Oct 2017 17:04:07 +0200 Subject: [PATCH 10/20] Added deploy to staging --- .gitlab-ci.yml | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c44507b1..1cc9797b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,9 +15,12 @@ variables: MYSQL_RANDOM_ROOT_PASSWORD: "yes" before_script: + # Fix permissions after gitlab messed them up + - find . -type f -exec chmod 644 {} \; + - find . -type d -exec chmod 755 {} \; # Install required Packages - - apt-get update -yqq - - apt-get install -yqq git unzip mysql-client + - apt update -yqq + - apt install -yqq git unzip mysql-client - docker-php-ext-install pdo pdo_mysql gettext # Install xdebug - pecl install xdebug @@ -45,3 +48,43 @@ test:7.0: test:7.1: image: php:7.1 <<: *test_definition + +deploy_staging: + stage: deploy + only: + - master + script: + - |- + if [ -z "${SSH_PRIVATE_KEY}" ] || [ -z "${REMOTE}" ] || [ -z "${REMOTE_PATH}" ]; then + echo "Skipping deployment"; + exit + fi + - mkdir -p ~/.ssh + - echo "$SSH_PRIVATE_KEY" | sed -e 's/\r//g' > ~/.ssh/id_ed25519 + - chmod 600 ~/.ssh/id_ed25519 + - apt update && apt install -yqq rsync openssh-client + - /usr/local/bin/composer --no-ansi install --no-dev + - /usr/local/bin/composer --no-ansi dump-autoload --optimize + - echo "syncing ${PWD}/ to ${REMOTE}:${REMOTE_PATH}/${CI_JOB_ID}-${CI_COMMIT_SHA}/" + - |- + rsync -vAax --exclude '.git*' --exclude .composer/ \ + -e "ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" \ + ./ "${REMOTE}:${REMOTE_PATH}/${CI_JOB_ID}-${CI_COMMIT_SHA}/" + - |- + ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "${REMOTE}" " + set -e + + if [[ -f \"${REMOTE_PATH}/current/config/config.php\" ]]; then + echo \"Config backup\" + cp \"${REMOTE_PATH}/current/config/config.php\" config.php + fi + + echo \"Changing symlink\" + unlink \"${REMOTE_PATH}/current\" + ln -s \"${REMOTE_PATH}/${CI_JOB_ID}-${CI_COMMIT_SHA}\" \"${REMOTE_PATH}/current\" + + if [[ -f config.php ]]; then + echo \"Restoring config\" + cp config.php \"${REMOTE_PATH}/current/config/config.php\" + fi + " From 60fd72cd1a1e4e53b9af87e00a8c27687c6b5385 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 31 Oct 2017 13:40:13 +0100 Subject: [PATCH 11/20] Added service providers --- config/app.php | 6 ++ includes/autoload.php | 2 +- includes/engelsystem_provider.php | 95 +++---------------- src/Application.php | 2 +- src/Config/ConfigServiceProvider.php | 26 +++++ src/Database/DatabaseServiceProvider.php | 31 ++++++ src/Exceptions/ExceptionsServiceProvider.php | 15 +++ src/Logger/LoggerServiceProvider.php | 18 ++++ src/Renderer/RendererServiceProvider.php | 36 +++++++ src/Routing/RoutingServiceProvider.php | 14 +++ .../DatabaseServiceProviderConnectionTest.php | 53 +++++++++++ .../Unit/Config/ConfigServiceProviderTest.php | 54 +++++++++++ .../Database/DatabaseServiceProviderTest.php | 49 ++++++++++ .../ExceptionsServiceProviderTest.php | 39 ++++++++ .../Unit/Logger/LoggerServiceProviderTest.php | 47 +++++++++ .../Renderer/RendererServiceProviderTest.php | 81 ++++++++++++++++ .../Routing/RoutingServiceProviderTest.php | 39 ++++++++ tests/Unit/ServiceProviderTest.php | 39 ++++++++ tests/autoload.php | 8 ++ 19 files changed, 572 insertions(+), 82 deletions(-) create mode 100644 src/Config/ConfigServiceProvider.php create mode 100644 src/Database/DatabaseServiceProvider.php create mode 100644 src/Exceptions/ExceptionsServiceProvider.php create mode 100644 src/Logger/LoggerServiceProvider.php create mode 100644 src/Renderer/RendererServiceProvider.php create mode 100644 src/Routing/RoutingServiceProvider.php create mode 100644 tests/Feature/Database/DatabaseServiceProviderConnectionTest.php create mode 100644 tests/Unit/Config/ConfigServiceProviderTest.php create mode 100644 tests/Unit/Database/DatabaseServiceProviderTest.php create mode 100644 tests/Unit/Exceptions/ExceptionsServiceProviderTest.php create mode 100644 tests/Unit/Logger/LoggerServiceProviderTest.php create mode 100644 tests/Unit/Renderer/RendererServiceProviderTest.php create mode 100644 tests/Unit/Routing/RoutingServiceProviderTest.php create mode 100644 tests/Unit/ServiceProviderTest.php create mode 100644 tests/autoload.php diff --git a/config/app.php b/config/app.php index fe0a97c1..8037479b 100644 --- a/config/app.php +++ b/config/app.php @@ -5,5 +5,11 @@ return [ // Service providers 'providers' => [ + \Engelsystem\Logger\LoggerServiceProvider::class, + \Engelsystem\Exceptions\ExceptionsServiceProvider::class, + \Engelsystem\Config\ConfigServiceProvider::class, + \Engelsystem\Routing\RoutingServiceProvider::class, + \Engelsystem\Renderer\RendererServiceProvider::class, + \Engelsystem\Database\DatabaseServiceProvider::class, ], ]; diff --git a/includes/autoload.php b/includes/autoload.php index f51f89e4..0cd9d355 100644 --- a/includes/autoload.php +++ b/includes/autoload.php @@ -6,4 +6,4 @@ if (!is_readable(__DIR__ . '/../vendor/autoload.php')) { } // Include composer autoloader -require_once __DIR__ . '/../vendor/autoload.php'; +$loader = require __DIR__ . '/../vendor/autoload.php'; diff --git a/includes/engelsystem_provider.php b/includes/engelsystem_provider.php index 3067ab62..48206cb6 100644 --- a/includes/engelsystem_provider.php +++ b/includes/engelsystem_provider.php @@ -2,14 +2,8 @@ use Engelsystem\Application; use Engelsystem\Config\Config; -use Engelsystem\Database\Db; use Engelsystem\Exceptions\Handler as ExceptionHandler; use Engelsystem\Http\Request; -use Engelsystem\Logger\EngelsystemLogger; -use Engelsystem\Renderer\HtmlEngine; -use Engelsystem\Renderer\Renderer; -use Engelsystem\Routing\UrlGenerator; -use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; @@ -21,78 +15,21 @@ require_once __DIR__ . '/autoload.php'; /** - * Initialize the application + * Initialize and bootstrap the application */ $app = new Application(realpath(__DIR__ . DIRECTORY_SEPARATOR . '..')); - - -/** - * Bootstrap application - */ $appConfig = $app->make(Config::class); -$appConfig->set(app('path.config') . '/app.php'); +$appConfig->set(require config_path('app.php')); $app->bootstrap($appConfig); -/** - * Load configuration - */ -$config = new Config(); -$app->instance('config', $config); -$config->set(require __DIR__ . '/../config/config.default.php'); - -if (file_exists(__DIR__ . '/../config/config.php')) { - $config->set(array_replace_recursive( - $config->get(null), - require __DIR__ . '/../config/config.php' - )); -} - /** * Configure application */ -date_default_timezone_set($config->get('timezone')); - - -/** - * Initialize Request - * - * @var Request $request - */ -$request = Request::createFromGlobals(); -$app->instance('request', $request); - - -/** - * Check for maintenance - */ -if ($app->get('config')->get('maintenance')) { - echo file_get_contents(__DIR__ . '/../templates/maintenance.html'); - die(); -} - - -/** - * Register UrlGenerator - */ -$urlGenerator = new UrlGenerator(); -$app->instance('routing.urlGenerator', $urlGenerator); +date_default_timezone_set($app->get('config')->get('timezone')); - -/** - * Initialize renderer - */ -$renderer = new Renderer(); -$app->instance('renderer', $renderer); -$renderer->addRenderer(new HtmlEngine()); - - -/** - * Register error handler - */ -$errorHandler = new ExceptionHandler(); -$app->instance('error.handler', $errorHandler); if (config('environment') == 'development') { + $errorHandler = $app->get('error.handler'); $errorHandler->setEnvironment(ExceptionHandler::ENV_DEVELOPMENT); ini_set('display_errors', true); error_reporting(E_ALL); @@ -102,23 +39,21 @@ if (config('environment') == 'development') { /** - * Connect to database + * Check for maintenance */ -Db::connect( - 'mysql:host=' . config('database')['host'] . ';dbname=' . config('database')['db'] . ';charset=utf8', - config('database')['user'], - config('database')['pw'] -) || die('Error: Unable to connect to database'); -Db::getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); -Db::getPdo()->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); +if ($app->get('config')->get('maintenance')) { + echo file_get_contents(__DIR__ . '/../templates/maintenance.html'); + die(); +} + /** - * Init logger + * Initialize Request + * + * @var Request $request */ -$logger = new EngelsystemLogger(); -$app->instance('logger', $logger); -$app->bind(LoggerInterface::class, 'logger'); -$app->bind(EngelsystemLogger::class, 'logger'); +$request = Request::createFromGlobals(); +$app->instance('request', $request); /** diff --git a/src/Application.php b/src/Application.php index b62b28a9..c9023c7b 100644 --- a/src/Application.php +++ b/src/Application.php @@ -54,7 +54,7 @@ class Application extends Container public function register($provider) { if (is_string($provider)) { - $provider = $this->get($provider); + $provider = $this->make($provider); } $this->serviceProviders[] = $provider; diff --git a/src/Config/ConfigServiceProvider.php b/src/Config/ConfigServiceProvider.php new file mode 100644 index 00000000..01b648df --- /dev/null +++ b/src/Config/ConfigServiceProvider.php @@ -0,0 +1,26 @@ +app->make(Config::class); + $this->app->instance('config', $config); + + $config->set(require $defaultConfigFile); + + if (file_exists($configFile)) { + $config->set(array_replace_recursive( + $config->get(null), + require $configFile + )); + } + } +} diff --git a/src/Database/DatabaseServiceProvider.php b/src/Database/DatabaseServiceProvider.php new file mode 100644 index 00000000..364816cc --- /dev/null +++ b/src/Database/DatabaseServiceProvider.php @@ -0,0 +1,31 @@ +app->get('config'); + Db::connect( + 'mysql:host=' . $config->get('database')['host'] . ';dbname=' . $config->get('database')['db'] . ';charset=utf8', + $config->get('database')['user'], + $config->get('database')['pw'] + ) || $this->exitOnError(); + + Db::getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + Db::getPdo()->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + } + + /** + * @throws Exception + */ + protected function exitOnError() + { + throw new Exception('Error: Unable to connect to database'); + } +} diff --git a/src/Exceptions/ExceptionsServiceProvider.php b/src/Exceptions/ExceptionsServiceProvider.php new file mode 100644 index 00000000..7755e1e7 --- /dev/null +++ b/src/Exceptions/ExceptionsServiceProvider.php @@ -0,0 +1,15 @@ +app->make(ExceptionHandler::class); + $this->app->instance('error.handler', $errorHandler); + } +} diff --git a/src/Logger/LoggerServiceProvider.php b/src/Logger/LoggerServiceProvider.php new file mode 100644 index 00000000..cf22f383 --- /dev/null +++ b/src/Logger/LoggerServiceProvider.php @@ -0,0 +1,18 @@ +app->make(EngelsystemLogger::class); + $this->app->instance('logger', $logger); + + $this->app->bind(LoggerInterface::class, 'logger'); + $this->app->bind(EngelsystemLogger::class, 'logger'); + } +} diff --git a/src/Renderer/RendererServiceProvider.php b/src/Renderer/RendererServiceProvider.php new file mode 100644 index 00000000..3e8d69bc --- /dev/null +++ b/src/Renderer/RendererServiceProvider.php @@ -0,0 +1,36 @@ +registerRenderer(); + $this->registerHtmlEngine(); + } + + public function boot() + { + $renderer = $this->app->get('renderer'); + + foreach ($this->app->tagged('renderer.engine') as $engine) { + $renderer->addRenderer($engine); + } + } + + protected function registerRenderer() + { + $renderer = $this->app->make(Renderer::class); + $this->app->instance('renderer', $renderer); + } + + protected function registerHtmlEngine() + { + $htmlEngine = $this->app->make(HtmlEngine::class); + $this->app->instance('renderer.htmlEngine', $htmlEngine); + $this->app->tag('renderer.htmlEngine', ['renderer.engine']); + } +} diff --git a/src/Routing/RoutingServiceProvider.php b/src/Routing/RoutingServiceProvider.php new file mode 100644 index 00000000..b7db1383 --- /dev/null +++ b/src/Routing/RoutingServiceProvider.php @@ -0,0 +1,14 @@ +app->make(UrlGenerator::class); + $this->app->instance('routing.urlGenerator', $urlGenerator); + } +} diff --git a/tests/Feature/Database/DatabaseServiceProviderConnectionTest.php b/tests/Feature/Database/DatabaseServiceProviderConnectionTest.php new file mode 100644 index 00000000..dd1ce729 --- /dev/null +++ b/tests/Feature/Database/DatabaseServiceProviderConnectionTest.php @@ -0,0 +1,53 @@ +getMockBuilder(Config::class) + ->getMock(); + + /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ + $app = $this->getMockBuilder(Application::class) + ->setMethods(['get']) + ->getMock(); + Application::setInstance($app); + + $app->expects($this->once()) + ->method('get') + ->with('config') + ->willReturn($config); + + $config->expects($this->atLeastOnce()) + ->method('get') + ->with('database') + ->willReturn($this->getDbConfig()); + + $serviceProvider = new DatabaseServiceProvider($app); + $serviceProvider->register(); + } + + private function getDbConfig() + { + $configValues = require __DIR__ . '/../../../config/config.default.php'; + $configFile = __DIR__ . '/../../../config/config.php'; + + if (file_exists($configFile)) { + $configValues = array_replace_recursive($configValues, require $configFile); + } + + return $configValues['database']; + } +} diff --git a/tests/Unit/Config/ConfigServiceProviderTest.php b/tests/Unit/Config/ConfigServiceProviderTest.php new file mode 100644 index 00000000..26128e79 --- /dev/null +++ b/tests/Unit/Config/ConfigServiceProviderTest.php @@ -0,0 +1,54 @@ +getMockBuilder(Config::class) + ->getMock(); + + /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ + $app = $this->getMockBuilder(Application::class) + ->setMethods(['make', 'instance', 'get']) + ->getMock(); + Application::setInstance($app); + + $app->expects($this->once()) + ->method('make') + ->with(Config::class) + ->willReturn($config); + + $app->expects($this->once()) + ->method('instance') + ->with('config', $config); + + $app->expects($this->atLeastOnce()) + ->method('get') + ->with('path.config') + ->willReturn(__DIR__ . '/../../../config'); + + $config->expects($this->exactly(2)) + ->method('set') + ->withAnyParameters(); + + $config->expects($this->once()) + ->method('get') + ->with(null) + ->willReturn([]); + + $serviceProvider = new ConfigServiceProvider($app); + $serviceProvider->register(); + } +} diff --git a/tests/Unit/Database/DatabaseServiceProviderTest.php b/tests/Unit/Database/DatabaseServiceProviderTest.php new file mode 100644 index 00000000..d0e3e164 --- /dev/null +++ b/tests/Unit/Database/DatabaseServiceProviderTest.php @@ -0,0 +1,49 @@ +getMockBuilder(Config::class) + ->getMock(); + + /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ + $app = $this->getMockBuilder(Application::class) + ->setMethods(['get']) + ->getMock(); + + $app->expects($this->once()) + ->method('get') + ->with('config') + ->willReturn($config); + + $config->expects($this->atLeastOnce()) + ->method('get') + ->with('database') + ->willReturn([ + 'host' => 'localhost', + 'db' => 'database', + 'user' => 'user', + 'pw' => 'password', + ]); + + $serviceProvider = new DatabaseServiceProvider($app); + $this->expectException(Exception::class); + + $serviceProvider->register(); + } +} diff --git a/tests/Unit/Exceptions/ExceptionsServiceProviderTest.php b/tests/Unit/Exceptions/ExceptionsServiceProviderTest.php new file mode 100644 index 00000000..26eddb75 --- /dev/null +++ b/tests/Unit/Exceptions/ExceptionsServiceProviderTest.php @@ -0,0 +1,39 @@ +getMockBuilder(ExceptionHandler::class) + ->getMock(); + + /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ + $app = $this->getMockBuilder(Application::class) + ->setMethods(['make', 'instance']) + ->getMock(); + + $app->expects($this->once()) + ->method('make') + ->with(ExceptionHandler::class) + ->willReturn($exceptionHandler); + + $app->expects($this->once()) + ->method('instance') + ->with('error.handler', $exceptionHandler); + + $serviceProvider = new ExceptionsServiceProvider($app); + $serviceProvider->register(); + } +} diff --git a/tests/Unit/Logger/LoggerServiceProviderTest.php b/tests/Unit/Logger/LoggerServiceProviderTest.php new file mode 100644 index 00000000..5143d236 --- /dev/null +++ b/tests/Unit/Logger/LoggerServiceProviderTest.php @@ -0,0 +1,47 @@ +getMockBuilder(EngelsystemLogger::class) + ->getMock(); + + /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ + $app = $this->getMockBuilder(Application::class) + ->setMethods(['make', 'instance', 'bind']) + ->getMock(); + + $app->expects($this->once()) + ->method('make') + ->with(EngelsystemLogger::class) + ->willReturn($logger); + + $app->expects($this->once()) + ->method('instance') + ->with('logger', $logger); + + $app->expects($this->atLeastOnce()) + ->method('bind') + ->withConsecutive( + [LoggerInterface::class, 'logger'], + [EngelsystemLogger::class, 'logger'] + ); + + $serviceProvider = new LoggerServiceProvider($app); + $serviceProvider->register(); + } +} diff --git a/tests/Unit/Renderer/RendererServiceProviderTest.php b/tests/Unit/Renderer/RendererServiceProviderTest.php new file mode 100644 index 00000000..f9044d8b --- /dev/null +++ b/tests/Unit/Renderer/RendererServiceProviderTest.php @@ -0,0 +1,81 @@ +getMockBuilder(Renderer::class) + ->getMock(); + /** @var PHPUnit_Framework_MockObject_MockObject|HtmlEngine $htmlEngine */ + $htmlEngine = $this->getMockBuilder(HtmlEngine::class) + ->getMock(); + + $app = $this->getApp(['make', 'instance', 'tag']); + + $app->expects($this->exactly(2)) + ->method('make') + ->withConsecutive( + [Renderer::class], + [HtmlEngine::class] + )->willReturnOnConsecutiveCalls( + $renderer, + $htmlEngine + ); + + $app->expects($this->exactly(2)) + ->method('instance') + ->withConsecutive( + ['renderer', $renderer], + ['renderer.htmlEngine', $htmlEngine] + ); + + $this->setExpects($app, 'tag', ['renderer.htmlEngine', ['renderer.engine']]); + + $serviceProvider = new RendererServiceProvider($app); + $serviceProvider->register(); + } + + /** + * @covers \Engelsystem\Renderer\RendererServiceProvider::boot() + */ + public function testBoot() + { + /** @var PHPUnit_Framework_MockObject_MockObject|Renderer $renderer */ + $renderer = $this->getMockBuilder(Renderer::class) + ->getMock(); + /** @var PHPUnit_Framework_MockObject_MockObject|EngineInterface $engine1 */ + $engine1 = $this->getMockForAbstractClass(EngineInterface::class); + /** @var PHPUnit_Framework_MockObject_MockObject|EngineInterface $engine2 */ + $engine2 = $this->getMockForAbstractClass(EngineInterface::class); + + $app = $this->getApp(['get', 'tagged']); + + $engines = [$engine1, $engine2]; + + $this->setExpects($app, 'get', ['renderer'], $renderer); + $this->setExpects($app, 'tagged', ['renderer.engine'], $engines); + + $invocation = $renderer + ->expects($this->exactly(count($engines))) + ->method('addRenderer'); + call_user_func_array([$invocation, 'withConsecutive'], $engines); + + $serviceProvider = new RendererServiceProvider($app); + $serviceProvider->boot(); + } +} diff --git a/tests/Unit/Routing/RoutingServiceProviderTest.php b/tests/Unit/Routing/RoutingServiceProviderTest.php new file mode 100644 index 00000000..4f1cd5fc --- /dev/null +++ b/tests/Unit/Routing/RoutingServiceProviderTest.php @@ -0,0 +1,39 @@ +getMockBuilder(UrlGenerator::class) + ->getMock(); + + /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ + $app = $this->getMockBuilder(Application::class) + ->setMethods(['make', 'instance']) + ->getMock(); + + $app->expects($this->once()) + ->method('make') + ->with(UrlGenerator::class) + ->willReturn($urlGenerator); + + $app->expects($this->once()) + ->method('instance') + ->with('routing.urlGenerator', $urlGenerator); + + $serviceProvider = new RoutingServiceProvider($app); + $serviceProvider->register(); + } +} diff --git a/tests/Unit/ServiceProviderTest.php b/tests/Unit/ServiceProviderTest.php new file mode 100644 index 00000000..be843742 --- /dev/null +++ b/tests/Unit/ServiceProviderTest.php @@ -0,0 +1,39 @@ +getMockBuilder(Application::class) + ->setMethods($methods) + ->getMock(); + } + + /** + * @param PHPUnit_Framework_MockObject_MockObject $object + * @param string $method + * @param array $arguments + * @param mixed $return + */ + protected function setExpects($object, $method, $arguments, $return = null) + { + $invocation = $object->expects($this->once()) + ->method($method); + call_user_func_array([$invocation, 'with'], $arguments); + + if (!is_null($return)) { + $invocation->willReturn($return); + } + } +} diff --git a/tests/autoload.php b/tests/autoload.php new file mode 100644 index 00000000..3168ce3d --- /dev/null +++ b/tests/autoload.php @@ -0,0 +1,8 @@ +addPsr4('Engelsystem\\Test\\', __DIR__ . '/'); From 915cbee3e099cc7d48f71f6627b5fde3942cbe88 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 31 Oct 2017 13:41:17 +0100 Subject: [PATCH 12/20] Merge branch 'noc0lour:fix_setup_bugs', closes #335 --- phpunit.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index bdc4b0b6..98e64795 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,5 +1,5 @@ @@ -13,7 +13,6 @@ - ./include/ ./src/ From 411ea5bb6d0ecf32e6c989a99fac120502db9fe9 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 31 Oct 2017 14:15:19 +0100 Subject: [PATCH 13/20] Refactored service provider tests --- .../Unit/Config/ConfigServiceProviderTest.php | 35 +++++-------------- .../Database/DatabaseServiceProviderTest.php | 34 ++++++------------ .../ExceptionsServiceProviderTest.php | 20 +++-------- .../Unit/Logger/LoggerServiceProviderTest.php | 20 +++-------- .../Routing/RoutingServiceProviderTest.php | 20 +++-------- tests/Unit/ServiceProviderTest.php | 31 ++++++++++------ 6 files changed, 55 insertions(+), 105 deletions(-) diff --git a/tests/Unit/Config/ConfigServiceProviderTest.php b/tests/Unit/Config/ConfigServiceProviderTest.php index 26128e79..96ac8704 100644 --- a/tests/Unit/Config/ConfigServiceProviderTest.php +++ b/tests/Unit/Config/ConfigServiceProviderTest.php @@ -5,10 +5,10 @@ namespace Engelsystem\Test\Config; use Engelsystem\Application; use Engelsystem\Config\Config; use Engelsystem\Config\ConfigServiceProvider; -use PHPUnit\Framework\TestCase; +use Engelsystem\Test\Unit\ServiceProviderTest; use PHPUnit_Framework_MockObject_MockObject; -class ConfigServiceProviderTest extends TestCase +class ConfigServiceProviderTest extends ServiceProviderTest { /** * @covers \Engelsystem\Config\ConfigServiceProvider::register() @@ -19,34 +19,15 @@ class ConfigServiceProviderTest extends TestCase $config = $this->getMockBuilder(Config::class) ->getMock(); - /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ - $app = $this->getMockBuilder(Application::class) - ->setMethods(['make', 'instance', 'get']) - ->getMock(); + $app = $this->getApp(['make', 'instance', 'get']); Application::setInstance($app); - $app->expects($this->once()) - ->method('make') - ->with(Config::class) - ->willReturn($config); - - $app->expects($this->once()) - ->method('instance') - ->with('config', $config); - - $app->expects($this->atLeastOnce()) - ->method('get') - ->with('path.config') - ->willReturn(__DIR__ . '/../../../config'); - - $config->expects($this->exactly(2)) - ->method('set') - ->withAnyParameters(); + $this->setExpects($app, 'make', [Config::class], $config); + $this->setExpects($app, 'instance', ['config', $config]); + $this->setExpects($app, 'get', ['path.config'], __DIR__ . '/../../../config', $this->atLeastOnce()); - $config->expects($this->once()) - ->method('get') - ->with(null) - ->willReturn([]); + $this->setExpects($config, 'set', null, null, $this->exactly(2)); + $this->setExpects($config, 'get', [null], []); $serviceProvider = new ConfigServiceProvider($app); $serviceProvider->register(); diff --git a/tests/Unit/Database/DatabaseServiceProviderTest.php b/tests/Unit/Database/DatabaseServiceProviderTest.php index d0e3e164..d61f5ae7 100644 --- a/tests/Unit/Database/DatabaseServiceProviderTest.php +++ b/tests/Unit/Database/DatabaseServiceProviderTest.php @@ -2,14 +2,13 @@ namespace Engelsystem\Test\Database; -use Engelsystem\Application; use Engelsystem\Config\Config; use Engelsystem\Database\DatabaseServiceProvider; +use Engelsystem\Test\Unit\ServiceProviderTest; use Exception; -use PHPUnit\Framework\TestCase; use PHPUnit_Framework_MockObject_MockObject; -class DatabaseServiceProviderTest extends TestCase +class DatabaseServiceProviderTest extends ServiceProviderTest { /** * @covers \Engelsystem\Database\DatabaseServiceProvider::register() @@ -21,29 +20,18 @@ class DatabaseServiceProviderTest extends TestCase $config = $this->getMockBuilder(Config::class) ->getMock(); - /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ - $app = $this->getMockBuilder(Application::class) - ->setMethods(['get']) - ->getMock(); - - $app->expects($this->once()) - ->method('get') - ->with('config') - ->willReturn($config); - - $config->expects($this->atLeastOnce()) - ->method('get') - ->with('database') - ->willReturn([ - 'host' => 'localhost', - 'db' => 'database', - 'user' => 'user', - 'pw' => 'password', - ]); + $app = $this->getApp(['get']); - $serviceProvider = new DatabaseServiceProvider($app); + $this->setExpects($app, 'get', ['config'], $config); + $this->setExpects($config, 'get', ['database'], [ + 'host' => 'localhost', + 'db' => 'database', + 'user' => 'user', + 'pw' => 'password', + ], $this->atLeastOnce()); $this->expectException(Exception::class); + $serviceProvider = new DatabaseServiceProvider($app); $serviceProvider->register(); } } diff --git a/tests/Unit/Exceptions/ExceptionsServiceProviderTest.php b/tests/Unit/Exceptions/ExceptionsServiceProviderTest.php index 26eddb75..fc48d39e 100644 --- a/tests/Unit/Exceptions/ExceptionsServiceProviderTest.php +++ b/tests/Unit/Exceptions/ExceptionsServiceProviderTest.php @@ -2,13 +2,12 @@ namespace Engelsystem\Test\Exceptions; -use Engelsystem\Application; use Engelsystem\Exceptions\ExceptionsServiceProvider; use Engelsystem\Exceptions\Handler as ExceptionHandler; -use PHPUnit\Framework\TestCase; +use Engelsystem\Test\Unit\ServiceProviderTest; use PHPUnit_Framework_MockObject_MockObject; -class ExceptionsServiceProviderTest extends TestCase +class ExceptionsServiceProviderTest extends ServiceProviderTest { /** * @covers \Engelsystem\Exceptions\ExceptionsServiceProvider::register() @@ -19,19 +18,10 @@ class ExceptionsServiceProviderTest extends TestCase $exceptionHandler = $this->getMockBuilder(ExceptionHandler::class) ->getMock(); - /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ - $app = $this->getMockBuilder(Application::class) - ->setMethods(['make', 'instance']) - ->getMock(); - - $app->expects($this->once()) - ->method('make') - ->with(ExceptionHandler::class) - ->willReturn($exceptionHandler); + $app = $this->getApp(); - $app->expects($this->once()) - ->method('instance') - ->with('error.handler', $exceptionHandler); + $this->setExpects($app, 'make', [ExceptionHandler::class], $exceptionHandler); + $this->setExpects($app, 'instance', ['error.handler', $exceptionHandler]); $serviceProvider = new ExceptionsServiceProvider($app); $serviceProvider->register(); diff --git a/tests/Unit/Logger/LoggerServiceProviderTest.php b/tests/Unit/Logger/LoggerServiceProviderTest.php index 5143d236..66f63cf4 100644 --- a/tests/Unit/Logger/LoggerServiceProviderTest.php +++ b/tests/Unit/Logger/LoggerServiceProviderTest.php @@ -2,14 +2,13 @@ namespace Engelsystem\Test\Logger; -use Engelsystem\Application; use Engelsystem\Logger\EngelsystemLogger; use Engelsystem\Logger\LoggerServiceProvider; -use PHPUnit\Framework\TestCase; +use Engelsystem\Test\Unit\ServiceProviderTest; use PHPUnit_Framework_MockObject_MockObject; use Psr\Log\LoggerInterface; -class LoggerServiceProviderTest extends TestCase +class LoggerServiceProviderTest extends ServiceProviderTest { /** * @covers \Engelsystem\Logger\LoggerServiceProvider::register() @@ -20,19 +19,10 @@ class LoggerServiceProviderTest extends TestCase $logger = $this->getMockBuilder(EngelsystemLogger::class) ->getMock(); - /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ - $app = $this->getMockBuilder(Application::class) - ->setMethods(['make', 'instance', 'bind']) - ->getMock(); - - $app->expects($this->once()) - ->method('make') - ->with(EngelsystemLogger::class) - ->willReturn($logger); + $app = $this->getApp(['make', 'instance', 'bind']); - $app->expects($this->once()) - ->method('instance') - ->with('logger', $logger); + $this->setExpects($app, 'make', [EngelsystemLogger::class], $logger); + $this->setExpects($app, 'instance', ['logger', $logger]); $app->expects($this->atLeastOnce()) ->method('bind') diff --git a/tests/Unit/Routing/RoutingServiceProviderTest.php b/tests/Unit/Routing/RoutingServiceProviderTest.php index 4f1cd5fc..bb2a1d65 100644 --- a/tests/Unit/Routing/RoutingServiceProviderTest.php +++ b/tests/Unit/Routing/RoutingServiceProviderTest.php @@ -2,13 +2,12 @@ namespace Engelsystem\Test\Routing; -use Engelsystem\Application; use Engelsystem\Routing\RoutingServiceProvider; use Engelsystem\Routing\UrlGenerator; -use PHPUnit\Framework\TestCase; +use Engelsystem\Test\Unit\ServiceProviderTest; use PHPUnit_Framework_MockObject_MockObject; -class RoutingServiceProviderTest extends TestCase +class RoutingServiceProviderTest extends ServiceProviderTest { /** * @covers \Engelsystem\Routing\RoutingServiceProvider::register() @@ -19,19 +18,10 @@ class RoutingServiceProviderTest extends TestCase $urlGenerator = $this->getMockBuilder(UrlGenerator::class) ->getMock(); - /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ - $app = $this->getMockBuilder(Application::class) - ->setMethods(['make', 'instance']) - ->getMock(); - - $app->expects($this->once()) - ->method('make') - ->with(UrlGenerator::class) - ->willReturn($urlGenerator); + $app = $this->getApp(); - $app->expects($this->once()) - ->method('instance') - ->with('routing.urlGenerator', $urlGenerator); + $this->setExpects($app, 'make', [UrlGenerator::class], $urlGenerator); + $this->setExpects($app, 'instance', ['routing.urlGenerator', $urlGenerator]); $serviceProvider = new RoutingServiceProvider($app); $serviceProvider->register(); diff --git a/tests/Unit/ServiceProviderTest.php b/tests/Unit/ServiceProviderTest.php index be843742..dc58a65e 100644 --- a/tests/Unit/ServiceProviderTest.php +++ b/tests/Unit/ServiceProviderTest.php @@ -4,33 +4,44 @@ namespace Engelsystem\Test\Unit; use Engelsystem\Application; use PHPUnit\Framework\TestCase; -use PHPUnit_Framework_MockObject_MockObject; +use PHPUnit_Framework_MockObject_Matcher_InvokedRecorder as InvokedRecorder; +use PHPUnit_Framework_MockObject_MockObject as MockObject; abstract class ServiceProviderTest extends TestCase { /** * @param array $methods - * @return Application|PHPUnit_Framework_MockObject_MockObject + * @return Application|MockObject */ protected function getApp($methods = ['make', 'instance']) { - /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ + /** @var MockObject|Application $app */ return $this->getMockBuilder(Application::class) ->setMethods($methods) ->getMock(); } /** - * @param PHPUnit_Framework_MockObject_MockObject $object - * @param string $method - * @param array $arguments - * @param mixed $return + * @param MockObject $object + * @param string $method + * @param array $arguments + * @param mixed $return + * @param InvokedRecorder $times */ - protected function setExpects($object, $method, $arguments, $return = null) + protected function setExpects($object, $method, $arguments = null, $return = null, $times = null) { - $invocation = $object->expects($this->once()) + if (is_null($times)) { + $times = $this->once(); + } + + $invocation = $object->expects($times) ->method($method); - call_user_func_array([$invocation, 'with'], $arguments); + + if (is_null($arguments)) { + $invocation->withAnyParameters(); + } else { + call_user_func_array([$invocation, 'with'], $arguments); + } if (!is_null($return)) { $invocation->willReturn($return); From e15e86362585f5d00d118653232584ed0920e533 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 31 Oct 2017 14:23:23 +0100 Subject: [PATCH 14/20] Added tests for base_path and config_path --- .../DatabaseServiceProviderConnectionTest.php | 2 +- .../Feature/Logger/EngelsystemLoggerTest.php | 2 +- .../{model => Model}/LogEntriesModelTest.php | 2 +- .../{model => Model}/RoomModelTest.php | 2 +- tests/Unit/ApplicationTest.php | 2 +- .../Unit/Config/ConfigServiceProviderTest.php | 2 +- tests/Unit/Config/ConfigTest.php | 2 +- .../Database/DatabaseServiceProviderTest.php | 2 +- .../ExceptionsServiceProviderTest.php | 2 +- tests/Unit/HelpersTest.php | 43 ++++++++++++++++++- .../Unit/Logger/LoggerServiceProviderTest.php | 2 +- tests/Unit/Renderer/HtmlEngineTest.php | 2 +- .../Renderer/RendererServiceProviderTest.php | 2 +- tests/Unit/Renderer/RendererTest.php | 6 ++- .../Routing/RoutingServiceProviderTest.php | 2 +- tests/Unit/Routing/UrlGeneratorTest.php | 2 +- 16 files changed, 60 insertions(+), 17 deletions(-) rename tests/Feature/{model => Model}/LogEntriesModelTest.php (95%) rename tests/Feature/{model => Model}/RoomModelTest.php (94%) diff --git a/tests/Feature/Database/DatabaseServiceProviderConnectionTest.php b/tests/Feature/Database/DatabaseServiceProviderConnectionTest.php index dd1ce729..636fba2e 100644 --- a/tests/Feature/Database/DatabaseServiceProviderConnectionTest.php +++ b/tests/Feature/Database/DatabaseServiceProviderConnectionTest.php @@ -1,6 +1,6 @@ assertEquals($class, app('some.name')); } + /** + * @covers \base_path() + */ + public function testBasePath() + { + /** @var MockObject|Application $app */ + $app = $this->getMockBuilder(Container::class) + ->getMock(); + Application::setInstance($app); + + $app->expects($this->atLeastOnce()) + ->method('get') + ->with('path') + ->willReturn('/foo/bar'); + + $this->assertEquals('/foo/bar', base_path()); + $this->assertEquals('/foo/bar/bla-foo.conf', base_path('bla-foo.conf')); + } + /** * @covers \config */ @@ -53,6 +73,25 @@ class HelpersTest extends TestCase $this->assertEquals(['user' => 'FooBar'], config('mail')); } + /** + * @covers \config_path() + */ + public function testConfigPath() + { + /** @var MockObject|Application $app */ + $app = $this->getMockBuilder(Container::class) + ->getMock(); + Application::setInstance($app); + + $app->expects($this->atLeastOnce()) + ->method('get') + ->with('path.config') + ->willReturn('/foo/conf'); + + $this->assertEquals('/foo/conf', config_path()); + $this->assertEquals('/foo/conf/bar.php', config_path('bar.php')); + } + /** * @covers \env */ @@ -146,7 +185,7 @@ class HelpersTest extends TestCase /** * @param string $alias * @param object $object - * @return Application|\PHPUnit_Framework_MockObject_MockObject + * @return Application|MockObject */ protected function getAppMock($alias, $object) { diff --git a/tests/Unit/Logger/LoggerServiceProviderTest.php b/tests/Unit/Logger/LoggerServiceProviderTest.php index 66f63cf4..cef95d5b 100644 --- a/tests/Unit/Logger/LoggerServiceProviderTest.php +++ b/tests/Unit/Logger/LoggerServiceProviderTest.php @@ -1,6 +1,6 @@ getMockForAbstractClass(EngineInterface::class); $nullRenderer->expects($this->atLeastOnce()) @@ -20,6 +22,7 @@ class RendererTest extends TestCase ->willReturn(false); $renderer->addRenderer($nullRenderer); + /** @var MockObject|EngineInterface $mockRenderer */ $mockRenderer = $this->getMockForAbstractClass(EngineInterface::class); $mockRenderer->expects($this->atLeastOnce()) @@ -42,6 +45,7 @@ class RendererTest extends TestCase { $renderer = new Renderer(); + /** @var MockObject|LoggerInterface $loggerMock */ $loggerMock = $this->getMockForAbstractClass(LoggerInterface::class); $loggerMock ->expects($this->once()) diff --git a/tests/Unit/Routing/RoutingServiceProviderTest.php b/tests/Unit/Routing/RoutingServiceProviderTest.php index bb2a1d65..dd9441eb 100644 --- a/tests/Unit/Routing/RoutingServiceProviderTest.php +++ b/tests/Unit/Routing/RoutingServiceProviderTest.php @@ -1,6 +1,6 @@ Date: Tue, 31 Oct 2017 14:48:29 +0100 Subject: [PATCH 15/20] Added Container\ServiceProvider test --- tests/Unit/Container/ServiceProviderTest.php | 22 +++++++++++++++++++ .../Stub/ServiceProviderImplementation.php | 10 +++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/Unit/Container/ServiceProviderTest.php create mode 100644 tests/Unit/Container/Stub/ServiceProviderImplementation.php diff --git a/tests/Unit/Container/ServiceProviderTest.php b/tests/Unit/Container/ServiceProviderTest.php new file mode 100644 index 00000000..8a9cb76e --- /dev/null +++ b/tests/Unit/Container/ServiceProviderTest.php @@ -0,0 +1,22 @@ +getApp(); + + $serviceProvider = new ServiceProviderImplementation($app); + + $this->assertInstanceOf(ServiceProvider::class, $serviceProvider); + } +} diff --git a/tests/Unit/Container/Stub/ServiceProviderImplementation.php b/tests/Unit/Container/Stub/ServiceProviderImplementation.php new file mode 100644 index 00000000..36ae2c38 --- /dev/null +++ b/tests/Unit/Container/Stub/ServiceProviderImplementation.php @@ -0,0 +1,10 @@ + Date: Tue, 31 Oct 2017 15:13:37 +0100 Subject: [PATCH 16/20] Fixed ConfigServiceProviderTest when no config file has been created --- tests/Unit/Config/ConfigServiceProviderTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/Unit/Config/ConfigServiceProviderTest.php b/tests/Unit/Config/ConfigServiceProviderTest.php index ab6fa67f..c8be4b7d 100644 --- a/tests/Unit/Config/ConfigServiceProviderTest.php +++ b/tests/Unit/Config/ConfigServiceProviderTest.php @@ -29,7 +29,17 @@ class ConfigServiceProviderTest extends ServiceProviderTest $this->setExpects($config, 'set', null, null, $this->exactly(2)); $this->setExpects($config, 'get', [null], []); + $configFile = __DIR__ . '/../../../config/config.php'; + $configExists = file_exists($configFile); + if (!$configExists) { + file_put_contents($configFile, 'register(); + + if (!$configExists) { + unlink($configFile); + } } } From 8c703e12029c2170ced5cafe4c91e9fd5f8414d9 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 31 Oct 2017 17:17:32 +0100 Subject: [PATCH 17/20] Added request test --- tests/Unit/Http/RequestTest.php | 98 +++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/Unit/Http/RequestTest.php diff --git a/tests/Unit/Http/RequestTest.php b/tests/Unit/Http/RequestTest.php new file mode 100644 index 00000000..3f317367 --- /dev/null +++ b/tests/Unit/Http/RequestTest.php @@ -0,0 +1,98 @@ + 'I\'m a test!'], + ['foo' => 'bar'] + ); + + $this->assertEquals('bar', $request->postData('foo')); + $this->assertEquals('LoremIpsum', $request->postData('test-key', 'LoremIpsum')); + } + + /** + * @covers \Engelsystem\Http\Request::input + */ + public function testInput() + { + $request = new Request( + ['foo' => 'I\'m a test!'], + ['foo' => 'bar'] + ); + + $this->assertEquals('I\'m a test!', $request->input('foo')); + $this->assertEquals('LoremIpsum', $request->input('test-key', 'LoremIpsum')); + } + + /** + * @covers \Engelsystem\Http\Request::has + */ + public function testHas() + { + $request = new Request([ + 'foo' => 'I\'m a test!', + 'bar' => '', + ]); + + $this->assertTrue($request->has('foo')); + $this->assertFalse($request->has('bar')); + } + + /** + * @covers \Engelsystem\Http\Request::path + */ + public function testPath() + { + /** @var MockObject|Request $request */ + $request = $this + ->getMockBuilder(Request::class) + ->setMethods(['getPathInfo']) + ->getMock(); + + $request + ->expects($this->atLeastOnce()) + ->method('getPathInfo') + ->willReturnOnConsecutiveCalls( + '/foo', + '/' + ); + + $this->assertEquals('foo', $request->path()); + $this->assertEquals('/', $request->path()); + } + + /** + * @covers \Engelsystem\Http\Request::url + */ + public function testUrl() + { + /** @var MockObject|Request $request */ + $request = $this + ->getMockBuilder(Request::class) + ->setMethods(['getUri']) + ->getMock(); + + $request + ->expects($this->atLeastOnce()) + ->method('getUri') + ->willReturnOnConsecutiveCalls( + 'http://foo.bar/bla/foo/', + 'https://lorem.ipsum/dolor/sit?amet=consetetur&sadipscing=elitr' + ); + + $this->assertEquals('http://foo.bar/bla/foo', $request->url()); + $this->assertEquals('https://lorem.ipsum/dolor/sit', $request->url()); + } +} From e55d5c7c15411eb58dd99113d94ee8ba55fd414a Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 31 Oct 2017 19:26:48 +0100 Subject: [PATCH 18/20] Added database tests --- ...st.php => DatabaseServiceProviderTest.php} | 21 +- tests/Feature/Database/DatabaseTest.php | 25 +++ tests/Unit/Database/DbTest.php | 192 ++++++++++++++++++ 3 files changed, 221 insertions(+), 17 deletions(-) rename tests/Feature/Database/{DatabaseServiceProviderConnectionTest.php => DatabaseServiceProviderTest.php} (58%) create mode 100644 tests/Feature/Database/DatabaseTest.php create mode 100644 tests/Unit/Database/DbTest.php diff --git a/tests/Feature/Database/DatabaseServiceProviderConnectionTest.php b/tests/Feature/Database/DatabaseServiceProviderTest.php similarity index 58% rename from tests/Feature/Database/DatabaseServiceProviderConnectionTest.php rename to tests/Feature/Database/DatabaseServiceProviderTest.php index 636fba2e..d5fdd108 100644 --- a/tests/Feature/Database/DatabaseServiceProviderConnectionTest.php +++ b/tests/Feature/Database/DatabaseServiceProviderTest.php @@ -5,21 +5,20 @@ namespace Engelsystem\Test\Feature\Database; use Engelsystem\Application; use Engelsystem\Config\Config; use Engelsystem\Database\DatabaseServiceProvider; -use PHPUnit\Framework\TestCase; -use PHPUnit_Framework_MockObject_MockObject; +use PHPUnit_Framework_MockObject_MockObject as MockObject; -class DatabaseServiceProviderConnectionTest extends TestCase +class DatabaseServiceProviderTest extends DatabaseTest { /** * @covers \Engelsystem\Database\DatabaseServiceProvider::register() */ public function testRegister() { - /** @var PHPUnit_Framework_MockObject_MockObject|Config $config */ + /** @var MockObject|Config $config */ $config = $this->getMockBuilder(Config::class) ->getMock(); - /** @var PHPUnit_Framework_MockObject_MockObject|Application $app */ + /** @var MockObject|Application $app */ $app = $this->getMockBuilder(Application::class) ->setMethods(['get']) ->getMock(); @@ -38,16 +37,4 @@ class DatabaseServiceProviderConnectionTest extends TestCase $serviceProvider = new DatabaseServiceProvider($app); $serviceProvider->register(); } - - private function getDbConfig() - { - $configValues = require __DIR__ . '/../../../config/config.default.php'; - $configFile = __DIR__ . '/../../../config/config.php'; - - if (file_exists($configFile)) { - $configValues = array_replace_recursive($configValues, require $configFile); - } - - return $configValues['database']; - } } diff --git a/tests/Feature/Database/DatabaseTest.php b/tests/Feature/Database/DatabaseTest.php new file mode 100644 index 00000000..11df6779 --- /dev/null +++ b/tests/Feature/Database/DatabaseTest.php @@ -0,0 +1,25 @@ +assertFalse($result); + + $result = Db::connect('sqlite::memory'); + $this->assertTrue($result); + } + + /** + * @covers \Engelsystem\Database\Db::query() + */ + public function testQuery() + { + $stm = Db::query('SELECT * FROM test_data'); + $this->assertEquals('00000', $stm->errorCode()); + + $stm = Db::query('SELECT * FROM test_data WHERE id = ?', [4]); + $this->assertEquals('00000', $stm->errorCode()); + } + + /** + * @covers \Engelsystem\Database\Db::unprepared() + */ + public function testUnprepared() + { + $return = Db::unprepared('SELECT * FROM test_data WHERE id = 3'); + $this->assertTrue($return); + } + + /** + * @covers \Engelsystem\Database\Db::select() + */ + public function testSelect() + { + $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\Db::selectOne() + */ + public function testSelectOne() + { + $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]); + $return = array_pop($return); + $this->assertTrue(!is_array($return)); + } + + /** + * @covers \Engelsystem\Database\Db::insert() + */ + public function testInsert() + { + $count = Db::insert("INSERT INTO test_data (id, data) VALUES (5, 'Some random text'), (6, 'another text')"); + $this->assertEquals(2, $count); + + $count = Db::insert('INSERT INTO test_data(id, data) VALUES (:id, :alias)', ['id' => 7, 'alias' => 'Blafoo']); + $this->assertEquals(1, $count); + } + + /** + * @covers \Engelsystem\Database\Db::update() + */ + public function testUpdate() + { + $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\Db::delete() + */ + public function testDelete() + { + $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); + } + + /** + * @covers \Engelsystem\Database\Db::statement() + */ + public function testStatement() + { + $return = Db::statement('SELECT * FROM test_data WHERE id = 3'); + $this->assertTrue($return); + + $return = Db::statement('SELECT * FROM test_data WHERE id = ?', [2]); + $this->assertTrue($return); + } + + /** + * @covers \Engelsystem\Database\Db::getError() + */ + public function testGetError() + { + try { + Db::statement('foo'); + } catch (Throwable $e) { + } + + $error = Db::getError(); + $this->assertTrue(is_array($error)); + $this->assertEquals('near "foo": syntax error', $error[2]); + + $db = new Db(); + $refObject = new ReflectionObject($db); + $refProperty = $refObject->getProperty('stm'); + $refProperty->setAccessible(true); + $refProperty->setValue(null, null); + + $error = Db::getError(); + $this->assertEquals([-1, null, null], $error); + } + + /** + * @covers \Engelsystem\Database\Db::getPdo() + */ + public function testGetPdo() + { + $pdo = Db::getPdo(); + $this->assertInstanceOf(PDO::class, $pdo); + } + + /** + * @covers \Engelsystem\Database\Db::getStm() + */ + public function testGetStm() + { + $stm = Db::getStm(); + $this->assertInstanceOf(PDOStatement::class, $stm); + } + + /** + * Setup in memory database + */ + protected function setUp() + { + Db::connect('sqlite::memory:'); + Db::getPdo()->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + Db::query( + ' + CREATE TABLE test_data( + id INT PRIMARY KEY NOT NULL, + data TEXT NOT NULL + ); + '); + Db::query('CREATE UNIQUE INDEX test_data_id_uindex ON test_data (id);'); + Db::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') + ;"); + } +} From e727b367cc77452b58bc2d9360bcde97b7572288 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Wed, 1 Nov 2017 12:35:45 +0100 Subject: [PATCH 19/20] Moved includes to own file --- includes/engelsystem.php | 77 +++++++++++++++++++ ...{engelsystem_provider.php => includes.php} | 70 ----------------- public/index.php | 6 +- .../Feature/Logger/EngelsystemLoggerTest.php | 2 +- tests/Feature/Model/LogEntriesModelTest.php | 2 +- tests/Feature/Model/RoomModelTest.php | 2 +- 6 files changed, 85 insertions(+), 74 deletions(-) create mode 100644 includes/engelsystem.php rename includes/{engelsystem_provider.php => includes.php} (70%) diff --git a/includes/engelsystem.php b/includes/engelsystem.php new file mode 100644 index 00000000..f9535847 --- /dev/null +++ b/includes/engelsystem.php @@ -0,0 +1,77 @@ +make(Config::class); +$appConfig->set(require config_path('app.php')); +$app->bootstrap($appConfig); + + +/** + * Configure application + */ +date_default_timezone_set($app->get('config')->get('timezone')); + +if (config('environment') == 'development') { + $errorHandler = $app->get('error.handler'); + $errorHandler->setEnvironment(ExceptionHandler::ENV_DEVELOPMENT); + ini_set('display_errors', true); + error_reporting(E_ALL); +} else { + ini_set('display_errors', false); +} + + +/** + * Check for maintenance + */ +if ($app->get('config')->get('maintenance')) { + echo file_get_contents(__DIR__ . '/../templates/maintenance.html'); + die(); +} + + +/** + * Initialize Request + * + * @var Request $request + */ +$request = Request::createFromGlobals(); +$app->instance('request', $request); + + +/** + * Include legacy code + */ +require __DIR__ . '/includes.php'; + + +/** + * Init application + */ +$sessionStorage = (PHP_SAPI != 'cli' ? new NativeSessionStorage(['cookie_httponly' => true]) : new MockArraySessionStorage()); +$session = new Session($sessionStorage); +$app->instance('session', $session); +$session->start(); +$request->setSession($session); + + +gettext_init(); + +load_auth(); diff --git a/includes/engelsystem_provider.php b/includes/includes.php similarity index 70% rename from includes/engelsystem_provider.php rename to includes/includes.php index 48206cb6..a42f960f 100644 --- a/includes/engelsystem_provider.php +++ b/includes/includes.php @@ -1,61 +1,5 @@ make(Config::class); -$appConfig->set(require config_path('app.php')); -$app->bootstrap($appConfig); - - -/** - * Configure application - */ -date_default_timezone_set($app->get('config')->get('timezone')); - -if (config('environment') == 'development') { - $errorHandler = $app->get('error.handler'); - $errorHandler->setEnvironment(ExceptionHandler::ENV_DEVELOPMENT); - ini_set('display_errors', true); - error_reporting(E_ALL); -} else { - ini_set('display_errors', false); -} - - -/** - * Check for maintenance - */ -if ($app->get('config')->get('maintenance')) { - echo file_get_contents(__DIR__ . '/../templates/maintenance.html'); - die(); -} - - -/** - * Initialize Request - * - * @var Request $request - */ -$request = Request::createFromGlobals(); -$app->instance('request', $request); - - /** * Include legacy code */ @@ -140,17 +84,3 @@ $includeFiles = [ foreach ($includeFiles as $file) { require_once realpath($file); } - - -/** - * Init application - */ -$sessionStorage = (PHP_SAPI != 'cli' ? new NativeSessionStorage(['cookie_httponly' => true]) : new MockArraySessionStorage()); -$session = new Session($sessionStorage); -$app->instance('session', $session); -$session->start(); -$request->setSession($session); - -gettext_init(); - -load_auth(); diff --git a/public/index.php b/public/index.php index c65dbdf8..69d92127 100644 --- a/public/index.php +++ b/public/index.php @@ -1,6 +1,8 @@ get('request'); $page = $request->query->get('p'); if (empty($page)) { $page = $request->path(); diff --git a/tests/Feature/Logger/EngelsystemLoggerTest.php b/tests/Feature/Logger/EngelsystemLoggerTest.php index 9f502198..8886d4ba 100644 --- a/tests/Feature/Logger/EngelsystemLoggerTest.php +++ b/tests/Feature/Logger/EngelsystemLoggerTest.php @@ -12,7 +12,7 @@ class EngelsystemLoggerTest extends TestCase { public static function setUpBeforeClass() { - require_once __DIR__ . '/../../../includes/engelsystem_provider.php'; + require_once __DIR__ . '/../../../includes/engelsystem.php'; } /** diff --git a/tests/Feature/Model/LogEntriesModelTest.php b/tests/Feature/Model/LogEntriesModelTest.php index 2678dcb5..036f5692 100644 --- a/tests/Feature/Model/LogEntriesModelTest.php +++ b/tests/Feature/Model/LogEntriesModelTest.php @@ -9,7 +9,7 @@ class LogEntriesModelTest extends TestCase { public static function setUpBeforeClass() { - require_once __DIR__ . '/../../../includes/engelsystem_provider.php'; + require_once __DIR__ . '/../../../includes/engelsystem.php'; } public function testCreateLogEntry() diff --git a/tests/Feature/Model/RoomModelTest.php b/tests/Feature/Model/RoomModelTest.php index 20b9e34d..3114ba2d 100644 --- a/tests/Feature/Model/RoomModelTest.php +++ b/tests/Feature/Model/RoomModelTest.php @@ -10,7 +10,7 @@ class RoomModelTest extends TestCase public static function setUpBeforeClass() { - require_once __DIR__ . '/../../../includes/engelsystem_provider.php'; + require_once __DIR__ . '/../../../includes/engelsystem.php'; } public function create_Room() From ad948bdd3201e922b626a736b0122533bdd37cae Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Wed, 1 Nov 2017 14:47:09 +0100 Subject: [PATCH 20/20] Added RequestServiceProvider and SessionServiceProvider --- config/app.php | 2 + includes/engelsystem.php | 34 ++--- src/Http/RequestServiceProvider.php | 14 ++ src/Http/SessionServiceProvider.php | 52 ++++++++ tests/Unit/Database/DbTest.php | 2 +- .../Unit/Http/RequestServiceProviderTest.php | 29 ++++ .../Unit/Http/SessionServiceProviderTest.php | 126 ++++++++++++++++++ 7 files changed, 233 insertions(+), 26 deletions(-) create mode 100644 src/Http/RequestServiceProvider.php create mode 100644 src/Http/SessionServiceProvider.php create mode 100644 tests/Unit/Http/RequestServiceProviderTest.php create mode 100644 tests/Unit/Http/SessionServiceProviderTest.php diff --git a/config/app.php b/config/app.php index 8037479b..74eb2991 100644 --- a/config/app.php +++ b/config/app.php @@ -11,5 +11,7 @@ return [ \Engelsystem\Routing\RoutingServiceProvider::class, \Engelsystem\Renderer\RendererServiceProvider::class, \Engelsystem\Database\DatabaseServiceProvider::class, + \Engelsystem\Http\RequestServiceProvider::class, + \Engelsystem\Http\SessionServiceProvider::class, ], ]; diff --git a/includes/engelsystem.php b/includes/engelsystem.php index f9535847..97076895 100644 --- a/includes/engelsystem.php +++ b/includes/engelsystem.php @@ -3,10 +3,6 @@ use Engelsystem\Application; use Engelsystem\Config\Config; use Engelsystem\Exceptions\Handler as ExceptionHandler; -use Engelsystem\Http\Request; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; /** * This file includes all needed functions, connects to the db etc. @@ -14,6 +10,12 @@ use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; require_once __DIR__ . '/autoload.php'; +/** + * Include legacy code + */ +require __DIR__ . '/includes.php'; + + /** * Initialize and bootstrap the application */ @@ -48,30 +50,12 @@ if ($app->get('config')->get('maintenance')) { /** - * Initialize Request - * - * @var Request $request + * Init translations */ -$request = Request::createFromGlobals(); -$app->instance('request', $request); - - -/** - * Include legacy code - */ -require __DIR__ . '/includes.php'; +gettext_init(); /** - * Init application + * Init authorization */ -$sessionStorage = (PHP_SAPI != 'cli' ? new NativeSessionStorage(['cookie_httponly' => true]) : new MockArraySessionStorage()); -$session = new Session($sessionStorage); -$app->instance('session', $session); -$session->start(); -$request->setSession($session); - - -gettext_init(); - load_auth(); diff --git a/src/Http/RequestServiceProvider.php b/src/Http/RequestServiceProvider.php new file mode 100644 index 00000000..077e9ecc --- /dev/null +++ b/src/Http/RequestServiceProvider.php @@ -0,0 +1,14 @@ +app->call([Request::class, 'createFromGlobals']); + $this->app->instance('request', $request); + } +} diff --git a/src/Http/SessionServiceProvider.php b/src/Http/SessionServiceProvider.php new file mode 100644 index 00000000..55e3f48b --- /dev/null +++ b/src/Http/SessionServiceProvider.php @@ -0,0 +1,52 @@ +getSessionStorage(); + $this->app->instance('session.storage', $sessionStorage); + $this->app->bind(SessionStorageInterface::class, 'session.storage'); + + $session = $this->app->make(Session::class); + $this->app->instance('session', $session); + + /** @var Request $request */ + $request = $this->app->get('request'); + $request->setSession($session); + + $session->start(); + } + + /** + * Returns the session storage + * + * @return SessionStorageInterface + */ + protected function getSessionStorage() + { + if ($this->isCli()) { + return $this->app->make(MockArraySessionStorage::class); + } + + return $this->app->make(NativeSessionStorage::class, ['options' => ['cookie_httponly' => true]]); + } + + /** + * Test if is called from cli + * + * @return bool + */ + protected function isCli() + { + return PHP_SAPI == 'cli'; + } +} diff --git a/tests/Unit/Database/DbTest.php b/tests/Unit/Database/DbTest.php index 4529cd6b..63607cad 100644 --- a/tests/Unit/Database/DbTest.php +++ b/tests/Unit/Database/DbTest.php @@ -19,7 +19,7 @@ class DbTest extends TestCase $result = Db::connect('mysql:host=localhost;dbname=someTestDatabaseThatDoesNotExist;charset=utf8'); $this->assertFalse($result); - $result = Db::connect('sqlite::memory'); + $result = Db::connect('sqlite::memory:'); $this->assertTrue($result); } diff --git a/tests/Unit/Http/RequestServiceProviderTest.php b/tests/Unit/Http/RequestServiceProviderTest.php new file mode 100644 index 00000000..a137b0ac --- /dev/null +++ b/tests/Unit/Http/RequestServiceProviderTest.php @@ -0,0 +1,29 @@ +getMockBuilder(Request::class) + ->getMock(); + + $app = $this->getApp(['call', 'instance']); + + $this->setExpects($app, 'call', [[Request::class, 'createFromGlobals']], $request); + $this->setExpects($app, 'instance', ['request', $request]); + + $serviceProvider = new RequestServiceProvider($app); + $serviceProvider->register(); + } +} diff --git a/tests/Unit/Http/SessionServiceProviderTest.php b/tests/Unit/Http/SessionServiceProviderTest.php new file mode 100644 index 00000000..0f17a1af --- /dev/null +++ b/tests/Unit/Http/SessionServiceProviderTest.php @@ -0,0 +1,126 @@ +getApp(['make', 'instance', 'bind', 'get']); + + $sessionStorage = $this->getMockForAbstractClass(StorageInterface::class); + $sessionStorage2 = $this->getMockForAbstractClass(StorageInterface::class); + + $session = $this->getSessionMock(); + $request = $this->getRequestMock(); + + /** @var MockObject|SessionServiceProvider $serviceProvider */ + $serviceProvider = $this->getMockBuilder(SessionServiceProvider::class) + ->setConstructorArgs([$app]) + ->setMethods(['isCli']) + ->getMock(); + $serviceProvider->expects($this->exactly(2)) + ->method('isCli') + ->willReturnOnConsecutiveCalls(true, false); + + $app->expects($this->exactly(4)) + ->method('make') + ->withConsecutive( + [MockArraySessionStorage::class], + [Session::class], + [NativeSessionStorage::class, ['options' => ['cookie_httponly' => true]]], + [Session::class] + ) + ->willReturnOnConsecutiveCalls( + $sessionStorage, + $session, + $sessionStorage2, + $session + ); + $app->expects($this->atLeastOnce()) + ->method('instance') + ->withConsecutive( + ['session.storage', $sessionStorage], + ['session', $session] + ); + + $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(); + } + + /** + * @covers \Engelsystem\Http\SessionServiceProvider::isCli() + */ + public function testIsCli() + { + $app = $this->getApp(['make', 'instance', 'bind', 'get']); + + $sessionStorage = $this->getMockForAbstractClass(StorageInterface::class); + + $session = $this->getSessionMock(); + $request = $this->getRequestMock(); + + $app->expects($this->exactly(2)) + ->method('make') + ->withConsecutive( + [MockArraySessionStorage::class], + [Session::class] + ) + ->willReturnOnConsecutiveCalls( + $sessionStorage, + $session + ); + $app->expects($this->exactly(2)) + ->method('instance') + ->withConsecutive( + ['session.storage', $sessionStorage], + ['session', $session] + ); + + $this->setExpects($app, 'bind', [StorageInterface::class, 'session.storage']); + $this->setExpects($app, 'get', ['request'], $request); + $this->setExpects($request, 'setSession', [$session]); + $this->setExpects($session, 'start'); + + $serviceProvider = new SessionServiceProvider($app); + $serviceProvider->register(); + } + + /** + * @return MockObject + */ + private function getSessionMock() + { + return $this->getMockBuilder(Session::class) + ->setMethods(['start']) + ->getMock(); + } + + /** + * @return MockObject + */ + private function getRequestMock() + { + return $this->getMockBuilder(Request::class) + ->setMethods(['setSession']) + ->getMock(); + } +}