From f845a5ab8b67e1d0b11779f1754bcc3f2193d67b Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sun, 28 Oct 2018 12:59:49 +0100 Subject: [PATCH] Added caching for templating and routing See #486 (Implement caching) --- includes/model/UserWorkLog_model.php | 2 +- src/Application.php | 6 +++- .../RouteDispatcherServiceProvider.php | 33 ++++++++++++++++--- src/Renderer/TwigServiceProvider.php | 16 ++++++++- storage/cache/.gitignore | 1 + storage/cache/views/.gitignore | 2 ++ tests/Unit/ApplicationTest.php | 4 +++ .../RouteDispatcherServiceProviderTest.php | 11 ++++++- .../Unit/Renderer/TwigServiceProviderTest.php | 16 ++++----- 9 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 storage/cache/.gitignore create mode 100644 storage/cache/views/.gitignore diff --git a/includes/model/UserWorkLog_model.php b/includes/model/UserWorkLog_model.php index 2b87c040..3b679cda 100644 --- a/includes/model/UserWorkLog_model.php +++ b/includes/model/UserWorkLog_model.php @@ -132,7 +132,7 @@ function UserWorkLog_new($userId) $work_date = parse_date('Y-m-d H:i', date('Y-m-d 00:00', time())); /** @var Carbon $buildup */ - $buildup = $buildup = config('buildup_start'); + $buildup = config('buildup_start'); if (!empty($buildup)) { $work_date = $buildup->format('Y-m-d H:i'); } diff --git a/src/Application.php b/src/Application.php index d12d3e31..02518423 100644 --- a/src/Application.php +++ b/src/Application.php @@ -108,8 +108,12 @@ class Application extends Container $this->instance('path.config', $appPath . DIRECTORY_SEPARATOR . 'config'); $this->instance('path.resources', $appPath . DIRECTORY_SEPARATOR . 'resources'); $this->instance('path.assets', $this->get('path.resources') . DIRECTORY_SEPARATOR . 'assets'); - $this->instance('path.views', $this->get('path.resources') . DIRECTORY_SEPARATOR . 'views'); $this->instance('path.lang', $this->get('path.resources') . DIRECTORY_SEPARATOR . 'lang'); + $this->instance('path.views', $this->get('path.resources') . DIRECTORY_SEPARATOR . 'views'); + $this->instance('path.storage', $appPath . DIRECTORY_SEPARATOR . 'storage'); + $this->instance('path.cache', $this->get('path.storage') . DIRECTORY_SEPARATOR . 'cache'); + $this->instance('path.cache.routes', $this->get('path.cache') . DIRECTORY_SEPARATOR . 'routes.cache.php'); + $this->instance('path.cache.views', $this->get('path.cache') . DIRECTORY_SEPARATOR . 'views'); } /** diff --git a/src/Middleware/RouteDispatcherServiceProvider.php b/src/Middleware/RouteDispatcherServiceProvider.php index 3b4fa183..193510f3 100644 --- a/src/Middleware/RouteDispatcherServiceProvider.php +++ b/src/Middleware/RouteDispatcherServiceProvider.php @@ -2,6 +2,7 @@ namespace Engelsystem\Middleware; +use Engelsystem\Config\Config; use Engelsystem\Container\ServiceProvider; use FastRoute\Dispatcher as FastRouteDispatcher; use FastRoute\RouteCollector; @@ -11,13 +12,24 @@ class RouteDispatcherServiceProvider extends ServiceProvider { public function register() { + /** @var Config $config */ + $config = $this->app->get('config'); + + $options = [ + 'cacheFile' => $this->app->get('path.cache.routes'), + ]; + + if ($config->get('environment') == 'development') { + $options['cacheDisabled'] = true; + } + $this->app->alias(RouteDispatcher::class, 'route.dispatcher'); $this->app ->when(RouteDispatcher::class) ->needs(FastRouteDispatcher::class) - ->give(function () { - return $this->generateRouting(); + ->give(function () use ($options) { + return $this->generateRouting($options); }); $this->app @@ -29,13 +41,24 @@ class RouteDispatcherServiceProvider extends ServiceProvider /** * Includes the routes.php file * + * @param array $options * @return FastRouteDispatcher * @codeCoverageIgnore */ - function generateRouting() + protected function generateRouting(array $options = []) { - return \FastRoute\simpleDispatcher(function (RouteCollector $route) { + $routesFile = config_path('routes.php'); + $routesCacheFile = $this->app->get('path.cache.routes'); + + if ( + file_exists($routesCacheFile) + && filemtime($routesFile) > filemtime($routesCacheFile) + ) { + unlink($routesCacheFile); + } + + return \FastRoute\cachedDispatcher(function (RouteCollector $route) { require config_path('routes.php'); - }); + }, $options); } } diff --git a/src/Renderer/TwigServiceProvider.php b/src/Renderer/TwigServiceProvider.php index 57ebe9e5..d7b6bd09 100644 --- a/src/Renderer/TwigServiceProvider.php +++ b/src/Renderer/TwigServiceProvider.php @@ -62,7 +62,21 @@ class TwigServiceProvider extends ServiceProvider $this->app->instance(TwigLoaderInterface::class, $twigLoader); $this->app->instance('twig.loader', $twigLoader); - $twig = $this->app->make(Twig::class); + $cache = $this->app->get('path.cache.views'); + if ($config->get('environment') == 'development') { + $cache = false; + } + + $twig = $this->app->make( + Twig::class, + [ + 'options' => [ + 'cache' => $cache, + 'auto_reload' => true, + 'strict_variables' => ($config->get('environment') == 'development'), + ], + ] + ); $this->app->instance(Twig::class, $twig); $this->app->instance('twig.environment', $twig); diff --git a/storage/cache/.gitignore b/storage/cache/.gitignore new file mode 100644 index 00000000..ea604cb2 --- /dev/null +++ b/storage/cache/.gitignore @@ -0,0 +1 @@ +/routes.cache.php diff --git a/storage/cache/views/.gitignore b/storage/cache/views/.gitignore new file mode 100644 index 00000000..78d91016 --- /dev/null +++ b/storage/cache/views/.gitignore @@ -0,0 +1,2 @@ +/* +!.gitignore diff --git a/tests/Unit/ApplicationTest.php b/tests/Unit/ApplicationTest.php index e6d77c7d..3fffe5ea 100644 --- a/tests/Unit/ApplicationTest.php +++ b/tests/Unit/ApplicationTest.php @@ -51,6 +51,10 @@ class ApplicationTest extends TestCase $this->assertTrue($app->has('path.lang')); $this->assertTrue($app->has('path.resources')); $this->assertTrue($app->has('path.views')); + $this->assertTrue($app->has('path.storage')); + $this->assertTrue($app->has('path.cache')); + $this->assertTrue($app->has('path.cache.routes')); + $this->assertTrue($app->has('path.cache.views')); $this->assertEquals(realpath('.'), $app->path()); $this->assertEquals(realpath('.') . '/config', $app->get('path.config')); diff --git a/tests/Unit/Middleware/RouteDispatcherServiceProviderTest.php b/tests/Unit/Middleware/RouteDispatcherServiceProviderTest.php index ca784c73..3947ac37 100644 --- a/tests/Unit/Middleware/RouteDispatcherServiceProviderTest.php +++ b/tests/Unit/Middleware/RouteDispatcherServiceProviderTest.php @@ -2,6 +2,7 @@ namespace Engelsystem\Test\Unit\Middleware; +use Engelsystem\Config\Config; use Engelsystem\Middleware\LegacyMiddleware; use Engelsystem\Middleware\RouteDispatcher; use Engelsystem\Middleware\RouteDispatcherServiceProvider; @@ -18,10 +19,18 @@ class RouteDispatcherServiceProviderTest extends ServiceProviderTest */ public function testRegister() { + /** @var ContextualBindingBuilder|MockObject $bindingBuilder */ $bindingBuilder = $this->createMock(ContextualBindingBuilder::class); + /** @var FastRouteDispatcher|MockObject $routeDispatcher */ $routeDispatcher = $this->getMockForAbstractClass(FastRouteDispatcher::class); + $config = new Config(['environment' => 'development']); - $app = $this->getApp(['alias', 'when']); + $app = $this->getApp(['alias', 'when', 'get']); + + $app->expects($this->exactly(2)) + ->method('get') + ->withConsecutive(['config'], ['path.cache.routes']) + ->willReturn($config, '/foo/routes.cache'); $app->expects($this->once()) ->method('alias') diff --git a/tests/Unit/Renderer/TwigServiceProviderTest.php b/tests/Unit/Renderer/TwigServiceProviderTest.php index 0d632633..86dee1de 100644 --- a/tests/Unit/Renderer/TwigServiceProviderTest.php +++ b/tests/Unit/Renderer/TwigServiceProviderTest.php @@ -91,7 +91,7 @@ class TwigServiceProviderTest extends ServiceProviderTest /** * @covers \Engelsystem\Renderer\TwigServiceProvider::registerTwigEngine */ - public function testRegisterTWigEngine() + public function testRegisterTwigEngine() { /** @var TwigEngine|MockObject $htmlEngine */ $twigEngine = $this->createMock(TwigEngine::class); @@ -114,7 +114,7 @@ class TwigServiceProviderTest extends ServiceProviderTest ->method('make') ->withConsecutive( [TwigLoader::class, ['paths' => $viewsPath]], - [Twig::class], + [Twig::class, ['options' => ['cache' => false, 'auto_reload' => true, 'strict_variables' => true]]], [TwigEngine::class] )->willReturnOnConsecutiveCalls( $twigLoader, @@ -133,17 +133,17 @@ class TwigServiceProviderTest extends ServiceProviderTest ['renderer.twigEngine', $twigEngine] ); - $app->expects($this->exactly(2)) + $app->expects($this->exactly(3)) ->method('get') - ->withConsecutive(['path.views'], ['config']) - ->willReturnOnConsecutiveCalls($viewsPath, $config); + ->withConsecutive(['path.views'], ['config'], ['path.cache.views']) + ->willReturnOnConsecutiveCalls($viewsPath, $config, 'cache/views'); $this->setExpects($app, 'tag', ['renderer.twigEngine', ['renderer.engine']]); - $config->expects($this->once()) + $config->expects($this->exactly(3)) ->method('get') - ->with('timezone') - ->willReturn('The/World'); + ->withConsecutive(['environment'], ['environment'], ['timezone']) + ->willReturnOnConsecutiveCalls('development', 'development', 'The/World'); $twig->expects($this->once()) ->method('getExtension')