diff --git a/CHANGELOG.md b/CHANGELOG.md index aa5d253..6d93d76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +## 1.0.0 - 2018-06-04 + +Migration to Zend-Expressive 3 + +### Changed +* Migrate middleware to PSR-15 + +### Added +* PSR-15 Middleware support + +### Deprecated +* Nothing + +### Removed +* Nothing + +### Fixed +* Nothing + + ## 0.4.1 - 2017-06-01 ### Changed diff --git a/composer.json b/composer.json index eeeb9db..6043990 100644 --- a/composer.json +++ b/composer.json @@ -5,8 +5,8 @@ "license": "MIT", "authors": [ { - "name": "n3vrax", - "email": "tibi@apidemia.com" + "name": "DotKernel Team", + "email": "team@dotkernel.com" } ], "config": { @@ -14,46 +14,46 @@ }, "require": { "php": "^7.1", - "dotkernel/dot-annotated-services": "^1.1", - "dotkernel/dot-authentication-service": "^0.2", - "dotkernel/dot-authentication-web": "^0.2", - "dotkernel/dot-cache": "^1.1", + "dotkernel/dot-annotated-services": "^1.1.1", + "dotkernel/dot-authentication-service": "^1.0", + "dotkernel/dot-authentication-web": "^1.0", + "dotkernel/dot-cache": "^1.1.1", "dotkernel/dot-console": "^0.1", - "dotkernel/dot-controller": "^0.3", - "dotkernel/dot-controller-plugin-authentication": "^0.2", - "dotkernel/dot-controller-plugin-authorization": "^0.2", - "dotkernel/dot-controller-plugin-flashmessenger": "^0.2", - "dotkernel/dot-controller-plugin-forms": "^0.2", - "dotkernel/dot-controller-plugin-mail": "^0.1", - "dotkernel/dot-controller-plugin-session": "^0.2", + "dotkernel/dot-controller": "^1.0", + "dotkernel/dot-controller-plugin-authentication": "^1.0", + "dotkernel/dot-controller-plugin-authorization": "^1.0", + "dotkernel/dot-controller-plugin-flashmessenger": "^1.0", + "dotkernel/dot-controller-plugin-forms": "^1.0", + "dotkernel/dot-controller-plugin-mail": "^1.0", + "dotkernel/dot-controller-plugin-session": "^1.0", "dotkernel/dot-event": "^0.2", "dotkernel/dot-filter": "^1.1", - "dotkernel/dot-flashmessenger": "^0.2", + "dotkernel/dot-flashmessenger": "^1.0", "dotkernel/dot-form": "^1.1", - "dotkernel/dot-helpers": "^0.2", + "dotkernel/dot-helpers": "^1.0", "dotkernel/dot-hydrator": "^1.1", "dotkernel/dot-inputfilter": "^1.1", "dotkernel/dot-log": "^1.1", - "dotkernel/dot-mail": "^0.1", - "dotkernel/dot-mapper": "^0.4", - "dotkernel/dot-navigation": "^0.2", + "dotkernel/dot-mail": "^1.0", + "dotkernel/dot-mapper": "^1.0", + "dotkernel/dot-navigation": "^1.0", "dotkernel/dot-paginator": "^1.1", - "dotkernel/dot-rbac": "^0.2", - "dotkernel/dot-rbac-guard": "^0.2", - "dotkernel/dot-session": "^2.0", - "dotkernel/dot-twigrenderer": "^0.2", - "dotkernel/dot-user": "^0.3", - "dotkernel/dot-validator": "^1.1", - "http-interop/http-middleware": "^0.4.1", + "dotkernel/dot-rbac": "^0.2.1", + "dotkernel/dot-rbac-guard": "^1.0", + "dotkernel/dot-session": "^3.0", + "dotkernel/dot-twigrenderer": "^1.0", + "dotkernel/dot-user": "^1.0", + "dotkernel/dot-validator": "^1.2.1", + "roave/security-advisories": "dev-master", "zendframework/zend-captcha": "^2.6", - "zendframework/zend-component-installer": "^1.0 || ^0.7.0", + "zendframework/zend-component-installer": "^2.0", "zendframework/zend-config": "^3.1", "zendframework/zend-config-aggregator": "^0.2.0", "zendframework/zend-db": "^2.8", - "zendframework/zend-expressive": "^2.0.2", - "zendframework/zend-expressive-fastroute": "^2.0", - "zendframework/zend-expressive-twigrenderer": "^1.4", + "zendframework/zend-expressive": "^3.0", + "zendframework/zend-expressive-fastroute": "^3.0", + "zendframework/zend-expressive-twigrenderer": "^2.0", "zendframework/zend-i18n": "^2.7", "zendframework/zend-i18n-resources": "^2.5", "zendframework/zend-psr7bridge": "^0.2.2", @@ -65,7 +65,7 @@ "require-dev": { "phpunit/phpunit": "^6.0.8 || ^5.7.15", "squizlabs/php_codesniffer": "^2.8.1", - "zendframework/zend-expressive-tooling": "^0.3.2", + "zendframework/zend-expressive-tooling": "^1.0", "filp/whoops": "^2.1.7", "zfcampus/zf-development-mode": "^3.1" }, @@ -103,8 +103,8 @@ }, "extra": { "branch-alias": { - "dev-master": "0.4-dev", - "dev-develop": "0.5-dev" + "dev-master": "1.0-dev", + "dev-develop": "1.1-dev" } } } diff --git a/config/config.php b/config/config.php index 0249201..4f8cc7d 100644 --- a/config/config.php +++ b/config/config.php @@ -10,6 +10,19 @@ 'config_cache_path' => __DIR__ . '/../data/config-cache.php', ]; $aggregator = new ConfigAggregator([ + // zend expressive & middleware factory + \Zend\Expressive\ConfigProvider::class, + +// router config + \Zend\Expressive\Router\ConfigProvider::class, + \Zend\Expressive\Router\FastRouteRouter\ConfigProvider::class, + + \Zend\Expressive\Twig\ConfigProvider::class, + \Zend\Expressive\Helper\ConfigProvider::class, + + // handler runner + \Zend\HttpHandlerRunner\ConfigProvider::class, + // Include cache configuration new ArrayProvider($cacheConfig), diff --git a/config/pipeline.php b/config/pipeline.php index 64583e8..0f46fe3 100644 --- a/config/pipeline.php +++ b/config/pipeline.php @@ -14,6 +14,13 @@ use Zend\Expressive\Middleware\NotFoundHandler; use Zend\Stratigility\Middleware\ErrorHandler; +// new middleware +use Psr\Container\ContainerInterface; +use Zend\Expressive\Application; +use Zend\Expressive\MiddlewareFactory; +use Zend\Expressive\Router\Middleware\RouteMiddleware; +use Zend\Expressive\Router\Middleware\DispatchMiddleware; + /** * Setup middleware pipeline: */ @@ -21,52 +28,54 @@ // The error handler should be the first (most outer) middleware to catch // all Exceptions. /** @var \Zend\Expressive\Application $app */ -$app->pipe(ErrorHandler::class); -$app->pipe(ServerUrlMiddleware::class); +return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void { + $app->pipe(ErrorHandler::class); + $app->pipe(ServerUrlMiddleware::class); -// starts the session and tracks session activity -$app->pipe(SessionMiddleware::class); + // starts the session and tracks session activity + $app->pipe(SessionMiddleware::class); -// automatically login the user if it has a valid remember token -$app->pipe(AutoLogin::class); + // automatically login the user if it has a valid remember token + $app->pipe(AutoLogin::class); -// Pipe more middleware here that you want to execute on every request: -// - bootstrapping -// - pre-conditions -// - modifications to outgoing responses + // Pipe more middleware here that you want to execute on every request: + // - bootstrapping + // - pre-conditions + // - modifications to outgoing responses -// Register the routing middleware in the middleware pipeline -$app->pipeRoutingMiddleware(); + // Register the routing middleware in the middleware pipeline + $app->pipe(RouteMiddleware::class); -// zend expressive middleware -$app->pipe(ImplicitHeadMiddleware::class); -$app->pipe(ImplicitOptionsMiddleware::class); -$app->pipe(UrlHelperMiddleware::class); + // zend expressive middleware + $app->pipe(ImplicitHeadMiddleware::class); + $app->pipe(ImplicitOptionsMiddleware::class); + $app->pipe(UrlHelperMiddleware::class); -// authentication and authorization error handlers -// this is piped here to have access to the route result -// it should be ok, as these particular errors are generated from below middleware or routed middleware -$app->pipe(ForbiddenHandler::class); -$app->pipe(UnauthorizedHandler::class); + // authentication and authorization error handlers + // this is piped here to have access to the route result + // it should be ok, as these particular errors are generated from below middleware or routed middleware + $app->pipe(ForbiddenHandler::class); + $app->pipe(UnauthorizedHandler::class); -// Add more middleware here that needs to introspect the routing results; this -// ... + // Add more middleware here that needs to introspect the routing results; this + // ... -// this middleware redirects to login or dashboard, based on authentication status, if `/` path is accessed -// this is just to make the UI more friendly, by by-passing the rbac guards in this particular case -$app->pipe(AdminIndexMiddleware::class); + // this middleware redirects to login or dashboard, based on authentication status, if `/` path is accessed + // this is just to make the UI more friendly, by by-passing the rbac guards in this particular case + $app->pipe(AdminIndexMiddleware::class); -// navigation middleware makes sure the navigation service is injected the RouteResult -$app->pipe(NavigationMiddleware::class); + // navigation middleware makes sure the navigation service is injected the RouteResult + $app->pipe(NavigationMiddleware::class); -// the RBAC guards protect chunks of the application(routes or controllers or controller actions) -// the authorization service can be used together with the guards for maximum security and finer control -$app->pipe(RbacGuardMiddleware::class); + // the RBAC guards protect chunks of the application(routes or controllers or controller actions) + // the authorization service can be used together with the guards for maximum security and finer control + $app->pipe(RbacGuardMiddleware::class); -// Register the dispatch middleware in the middleware pipeline -$app->pipeDispatchMiddleware(); + // Register the dispatch middleware in the middleware pipeline + $app->pipe(DispatchMiddleware::class); -// At this point, if no Response is return by any middleware, the -// NotFoundHandler kicks in; alternately, you can provide other fallback -// middleware to execute. -$app->pipe(NotFoundHandler::class); + // At this point, if no Response is return by any middleware, the + // NotFoundHandler kicks in; alternately, you can provide other fallback + // middleware to execute. + $app->pipe(NotFoundHandler::class); +}; diff --git a/config/routes.php b/config/routes.php index d758034..5494594 100644 --- a/config/routes.php +++ b/config/routes.php @@ -7,44 +7,53 @@ use Dot\Authentication\Web\Action\LogoutAction; use Dot\User\Controller\UserController as UserController; -/** - * Setup routes with a single request method: - * - * $app->get('/', App\Action\HomePageAction::class, 'home'); - * $app->post('/album', App\Action\AlbumCreateAction::class, 'album.create'); - * $app->put('/album/:id', App\Action\AlbumUpdateAction::class, 'album.put'); - * $app->patch('/album/:id', App\Action\AlbumUpdateAction::class, 'album.patch'); - * $app->delete('/album/:id', App\Action\AlbumDeleteAction::class, 'album.delete'); - * - * Or with multiple request methods: - * - * $app->route('/contact', App\Action\ContactAction::class, ['GET', 'POST', ...], 'contact'); - * - * Or handling all request methods: - * - * $app->route('/contact', App\Action\ContactAction::class)->setName('contact'); - * - * or: - * - * $app->route( - * '/contact', - * App\Action\ContactAction::class, - * Zend\Expressive\Router\Route::HTTP_METHOD_ANY, - * 'contact' - * ); - */ +// new middleware +use Psr\Container\ContainerInterface; +use Zend\Expressive\Application; +use Zend\Expressive\MiddlewareFactory; +use Zend\Expressive\Router\Middleware\RouteMiddleware; +use Zend\Expressive\Router\Middleware\DispatchMiddleware; -/** @var \Zend\Expressive\Application $app */ -// Dashboard controller route -$app->route('/dashboard[/{action}]', DashboardController::class, ['GET', 'POST'], 'dashboard'); +return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void { + /** + * Setup routes with a single request method: + * + * $app->get('/', App\Action\HomePageAction::class, 'home'); + * $app->post('/album', App\Action\AlbumCreateAction::class, 'album.create'); + * $app->put('/album/:id', App\Action\AlbumUpdateAction::class, 'album.put'); + * $app->patch('/album/:id', App\Action\AlbumUpdateAction::class, 'album.patch'); + * $app->delete('/album/:id', App\Action\AlbumDeleteAction::class, 'album.delete'); + * + * Or with multiple request methods: + * + * $app->route('/contact', App\Action\ContactAction::class, ['GET', 'POST', ...], 'contact'); + * + * Or handling all request methods: + * + * $app->route('/contact', App\Action\ContactAction::class)->setName('contact'); + * + * or: + * + * $app->route( + * '/contact', + * App\Action\ContactAction::class, + * Zend\Expressive\Router\Route::HTTP_METHOD_ANY, + * 'contact' + * ); + */ -// following three routes are for user(in this case user refers to the admin user) authentication and management -$app->route('/admin/login', LoginAction::class, ['GET', 'POST'], 'login'); -$app->route('/admin/logout', LogoutAction::class, ['GET'], 'logout'); -$app->route('/admin[/{action}[/{id}]]', [AdminController::class, UserController::class], ['GET', 'POST'], 'user'); + /** @var \Zend\Expressive\Application $app */ + // Dashboard controller route + $app->route('/dashboard[/{action}]', DashboardController::class, ['GET', 'POST'], 'dashboard'); -// this route is for the frontend user management(hence the f_ prefix) -// if this admin application is used without the frontend application(no frontend user management required) -// you can remove the Admin\User module together with any configuration related to it -// TODO: we'll offer the option to use admin package without frontend in future releases, as installation scripts -$app->route('/user[/{action}[/{id}]]', UserManagementController::class, ['GET', 'POST'], 'f_user'); + // following three routes are for user(in this case user refers to the admin user) authentication and management + $app->route('/admin/login', LoginAction::class, ['GET', 'POST'], 'login'); + $app->route('/admin/logout', LogoutAction::class, ['GET'], 'logout'); + $app->route('/admin[/{action}[/{id}]]', [AdminController::class, UserController::class], ['GET', 'POST'], 'user'); + + // this route is for the frontend user management(hence the f_ prefix) + // if this admin application is used without the frontend application(no frontend user management required) + // you can remove the Admin\User module together with any configuration related to it + // TODO: we'll offer the option to use admin package without frontend in future releases, as installation scripts + $app->route('/user[/{action}[/{id}]]', UserManagementController::class, ['GET', 'POST'], 'f_user'); +}; diff --git a/docs/Migration.md b/docs/Migration.md new file mode 100644 index 0000000..399fd5e --- /dev/null +++ b/docs/Migration.md @@ -0,0 +1,169 @@ +DotKernel3 Migration +--- + +Migration from Zend Expressive 2 to 3. + + +## Packages + +In `composer.json` replace the matching repositories with the following: + +``` +"dotkernel/dot-authentication-service":"^1.0", +"dotkernel/dot-authentication-web":"^1.0.1", +"dotkernel/dot-authentication":"^1.0" +"dotkernel/dot-controller":"^1.0", +"dotkernel/dot-controller-plugin-authentication":"^1.0", +"dotkernel/dot-controller-plugin-authorization":"^1.0", +"dotkernel/dot-controller-plugin-flashmessenger":"^1.0", +"dotkernel/dot-controller-plugin-forms":"^1.0", +"dotkernel/dot-controller-plugin-mail":"^1.0", +"dotkernel/dot-controller-plugin-session":"^1.0", +"dotkernel/dot-flashmessenger":"^1.0", +"dotkernel/dot-helpers":"^1.0", +"dotkernel/dot-mail":"^1.0", +"dotkernel/dot-mapper":"^1.0", +"dotkernel/dot-navigation":"^1.0", +"dotkernel/dot-rbac":"^0.2.1", +"dotkernel/dot-rbac-guard":"^1.0", +"dotkernel/dot-session":"^3.0", +"dotkernel/dot-twigrenderer":"^1.1", +"dotkernel/dot-user":"^1.0", + +"zendframework/zend-stratigility": "^3.0", +"zendframework/zend-expressive": "^3.0", +"zendframework/zend-expressive-template": "^2.0", +"zendframework/zend-expressive-router": "^3.0", +"zendframework/zend-expressive-fastroute": "^3.0", +"zendframework/zend-expressive-tooling": "^1.0", +``` +also update require-dev dependencies +``` +"zendframework/zend-expressive-tooling:": "^1.0", +"zendframework/zend-component-installer": "^2.0", + +``` + +Remove packages: +* http-interop/http-middleware +* webimpress/http-middleware-compatibility +``` +composer require dotkernel/dot-authentication-service:^1.0\ + dotkernel/dot-authentication-service:^1.0\ + dotkernel/dot-authentication-web:^1.0.1\ + dotkernel/dot-authentication:^1.0\ + dotkernel/dot-controller:^1.0\ + dotkernel/dot-controller-plugin-authentication:^1.0\ + dotkernel/dot-controller-plugin-authorization:^1.0\ + dotkernel/dot-controller-plugin-forms:^1.0\ + dotkernel/dot-controller-plugin-flashmessenger:^1.0\ + dotkernel/dot-controller-plugin-mail:^1.0\ + dotkernel/dot-controller-plugin-session:^1.0\ + dotkernel/dot-flashmessenger:^1.0\ + dotkernel/dot-helpers:^1.0\ + dotkernel/dot-mail:^1.0\ + dotkernel/dot-mapper:^1.0\ + dotkernel/dot-navigation:^1.0\ + dotkernel/dot-rbac-guard:^1.0\ + dotkernel/dot-session:^3.0\ + dotkernel/dot-twigrenderer:^1.1\ + dotkernel/dot-user:^1.0\ + dotkernel/dot-rbac:^0.2.1\ + zendframework/zend-expressive-helpers:^5.0\ + zendframework/zend-expressive-twigrenderer:^2.0\ + zendframework/zend-expressive-template:^2.0\ + zendframework/zend-expressive:^3.0\ + zendframework/zend-expressive-fastroute:^3.0\ + zendframework/zend-expressive-tooling:^1.0\ + zendframework/zend-expressive-router:^3.0\ + zendframework/zend-stratigility:^3.0\ + zendframework/zend-component-installer:^2.0 + +composer remove http-interop/http-middleware\ + webimpress/http-middleware-compatibility + + +``` + +## Configurations + +### Main Configuration +In `config/config.php` add the following config providers: + +```php +// zend expressive & middleware factory +\Zend\Expressive\ConfigProvider::class, + +// router config +\Zend\Expressive\Router\ConfigProvider::class, +\Zend\Expressive\Router\FastRouteRouter\ConfigProvider::class, + +\Zend\Expressive\Twig\ConfigProvider::class, +\Zend\Expressive\Helper\ConfigProvider::class, + +// handler runner +\Zend\HttpHandlerRunner\ConfigProvider::class, +``` + +Make sure they are the first ConfigProviders or before cached config (`ArrayProvider`) + +### Routing + +Wrap routing from `config/routes.php` in a callable with the following format: + +```php +return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void { + /** @var \Zend\Expressive\Application $app */ + $app->route('/', [PageController::class], ['GET', 'POST'], 'home'); +}; +``` + +add the following use statements and make sure the names are not duplicate: + +```php +use Psr\Container\ContainerInterface; +use Zend\Expressive\Application; +use Zend\Expressive\MiddlewareFactory; +``` + +### Pipeline + +Wrap routing from `config/pipeline.php` in a callable with the following format: + +```php +return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void { + /** @var \Zend\Expressive\Application $app */ + $app->route('/', [PageController::class], ['GET', 'POST'], 'home'); +}; +``` + +add the following use statements and make sure the names are not duplicate: + +```php +use Psr\Container\ContainerInterface; +use Zend\Expressive\Application; +use Zend\Expressive\MiddlewareFactory; +``` + + +#### Routing middleware migration + +add the following use statements +```php +use Zend\Expressive\Router\Middleware\RouteMiddleware; +use Zend\Expressive\Router\Middleware\DispatchMiddleware; +``` + +Replace the following lines to reflect the changes: + +`$app->pipeRoutingMiddleware();` -> `$app->pipe(RouteMiddleware::class);` +`$app->pipeDispatchMiddleware();` -> `$app->pipe(DispatchMiddleware::class);` + + + + + + + + + diff --git a/docs/Migration/config/config.php.dist b/docs/Migration/config/config.php.dist new file mode 100644 index 0000000..4f8cc7d --- /dev/null +++ b/docs/Migration/config/config.php.dist @@ -0,0 +1,87 @@ + __DIR__ . '/../data/config-cache.php', +]; +$aggregator = new ConfigAggregator([ + // zend expressive & middleware factory + \Zend\Expressive\ConfigProvider::class, + +// router config + \Zend\Expressive\Router\ConfigProvider::class, + \Zend\Expressive\Router\FastRouteRouter\ConfigProvider::class, + + \Zend\Expressive\Twig\ConfigProvider::class, + \Zend\Expressive\Helper\ConfigProvider::class, + + // handler runner + \Zend\HttpHandlerRunner\ConfigProvider::class, + + // Include cache configuration + new ArrayProvider($cacheConfig), + + //zend framework configs + \Zend\Db\ConfigProvider::class, + \Zend\Mail\ConfigProvider::class, + + // dotkernel components default configs + // some of these configs are overwriting and customizing the underlying zendframework configs + // in case the dotkernel package is heavily based on a zendframework package + // you should not include both zendframework config provider and dotkernel's config provider in this case + // e.g: dot-filter, dot-paginator, dot-session etc. + \Dot\AnnotatedServices\ConfigProvider::class, + \Dot\Authentication\ConfigProvider::class, + \Dot\Authentication\Web\ConfigProvider::class, + \Dot\Cache\ConfigProvider::class, + \Dot\Controller\ConfigProvider::class, + \Dot\Controller\Plugin\Authentication\ConfigProvider::class, + \Dot\Controller\Plugin\Authorization\ConfigProvider::class, + \Dot\Controller\Plugin\FlashMessenger\ConfigProvider::class, + \Dot\Controller\Plugin\Mail\ConfigProvider::class, + \Dot\Controller\Plugin\Forms\ConfigProvider::class, + \Dot\Controller\Plugin\Session\ConfigProvider::class, + \Dot\Mapper\ConfigProvider::class, + \Dot\Event\ConfigProvider::class, + \Dot\Filter\ConfigProvider::class, + \Dot\FlashMessenger\ConfigProvider::class, + \Dot\Form\ConfigProvider::class, + \Dot\Helpers\ConfigProvider::class, + \Dot\Hydrator\ConfigProvider::class, + \Dot\InputFilter\ConfigProvider::class, + \Dot\Log\ConfigProvider::class, + \Dot\Mail\ConfigProvider::class, + \Dot\Navigation\ConfigProvider::class, + \Dot\Paginator\ConfigProvider::class, + \Dot\Rbac\ConfigProvider::class, + \Dot\Rbac\Guard\ConfigProvider::class, + \Dot\Session\ConfigProvider::class, + \Dot\Twig\ConfigProvider::class, + \Dot\User\ConfigProvider::class, + \Dot\Validator\ConfigProvider::class, + \Dot\Console\ConfigProvider::class, + + //application + \Admin\Admin\ConfigProvider::class, + \Admin\User\ConfigProvider::class, + \Admin\App\ConfigProvider::class, + \Admin\Console\ConfigProvider::class, + + // Load application config in a pre-defined order in such a way that local settings + // overwrite global settings. (Loaded as first to last): + // - `global.php` + // - `*.global.php` + // - `local.php` + // - `*.local.php` + new PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'), + + // Load development config if it exists + new PhpFileProvider('config/development.config.php'), +], $cacheConfig['config_cache_path']); + +return $aggregator->getMergedConfig(); diff --git a/docs/Migration/config/pipeline.php.dist b/docs/Migration/config/pipeline.php.dist new file mode 100644 index 0000000..f54f3a1 --- /dev/null +++ b/docs/Migration/config/pipeline.php.dist @@ -0,0 +1,76 @@ +pipe(ErrorHandler::class); + $app->pipe(ServerUrlMiddleware::class); + + // starts the session and tracks session activity + $app->pipe(SessionMiddleware::class); + + // automatically login the user if it has a valid remember token + $app->pipe(AutoLogin::class); + + // Pipe more middleware here that you want to execute on every request: + // - bootstrapping + // - pre-conditions + // - modifications to outgoing responses + + // Register the routing middleware in the middleware pipeline + $app->pipe(RouteMiddleware::class); + + // zend expressive middleware + $app->pipe(ImplicitHeadMiddleware::class); + $app->pipe(ImplicitOptionsMiddleware::class); + $app->pipe(UrlHelperMiddleware::class); + + // authentication and authorization error handlers + // this is piped here to have access to the route result + // it should be ok, as these particular errors are generated from below middleware or routed middleware + $app->pipe(ForbiddenHandler::class); + $app->pipe(UnauthorizedHandler::class); + + // Add more middleware here that needs to introspect the routing results; this + // ... + + // navigation middleware makes sure the navigation service is injected the RouteResult + $app->pipe(NavigationMiddleware::class); + + // the RBAC guards protect chunks of the application(routes or controllers or controller actions) + // the authorization service can be used together with the guards for maximum security and finer control + $app->pipe(RbacGuardMiddleware::class); + + // Register the dispatch middleware in the middleware pipeline + $app->pipe(DispatchMiddleware::class); + + // At this point, if no Response is return by any middleware, the + // NotFoundHandler kicks in; alternately, you can provide other fallback + // middleware to execute. + $app->pipe(NotFoundHandler::class); +}; diff --git a/docs/Migration/config/routes.php.dist b/docs/Migration/config/routes.php.dist new file mode 100644 index 0000000..c053b3a --- /dev/null +++ b/docs/Migration/config/routes.php.dist @@ -0,0 +1,54 @@ +get('/', App\Action\HomePageAction::class, 'home'); + * $app->post('/album', App\Action\AlbumCreateAction::class, 'album.create'); + * $app->put('/album/:id', App\Action\AlbumUpdateAction::class, 'album.put'); + * $app->patch('/album/:id', App\Action\AlbumUpdateAction::class, 'album.patch'); + * $app->delete('/album/:id', App\Action\AlbumDeleteAction::class, 'album.delete'); + * + * Or with multiple request methods: + * + * $app->route('/contact', App\Action\ContactAction::class, ['GET', 'POST', ...], 'contact'); + * + * Or handling all request methods: + * + * $app->route('/contact', App\Action\ContactAction::class)->setName('contact'); + * + * or: + * + * $app->route( + * '/contact', + * App\Action\ContactAction::class, + * Zend\Expressive\Router\Route::HTTP_METHOD_ANY, + * 'contact' + * ); + */ + + /** @var \Zend\Expressive\Application $app */ + + $app->route('/', [PageController::class], ['GET', 'POST'], 'home'); + +// following three routes are for user functionality + $app->route('/user/login', LoginAction::class, ['GET', 'POST'], 'login'); + $app->route('/user/logout', LogoutAction::class, ['GET'], 'logout'); + $app->route('/user[/{action}]', [FrontendUserController::class, UserController::class], ['GET', 'POST'], 'user'); + + $app->route('/contact[/{action}]', [ContactController::class], ['GET', 'POST'], 'contact'); + $app->route('/page[/{action}]', [PageController::class], ['GET', 'POST'], 'page'); +}; diff --git a/docs/Migration/public/index.php.dist b/docs/Migration/public/index.php.dist new file mode 100644 index 0000000..fd11502 --- /dev/null +++ b/docs/Migration/public/index.php.dist @@ -0,0 +1,30 @@ +get(\Zend\Expressive\Application::class); + $factory = $container->get(\Zend\Expressive\MiddlewareFactory::class); + + // Execute programmatic/declarative middleware pipeline and routing + // configuration statements + (require 'config/pipeline.php')($app, $factory, $container); + (require 'config/routes.php')($app, $factory, $container); + + $app->run(); +})(); diff --git a/public/index.php b/public/index.php index 0fad61d..fd11502 100644 --- a/public/index.php +++ b/public/index.php @@ -1,9 +1,9 @@ get(\Zend\Expressive\Application::class); + $factory = $container->get(\Zend\Expressive\MiddlewareFactory::class); - // Import programmatic/declarative middleware pipeline and routing + // Execute programmatic/declarative middleware pipeline and routing // configuration statements - require 'config/pipeline.php'; - require 'config/routes.php'; + (require 'config/pipeline.php')($app, $factory, $container); + (require 'config/routes.php')($app, $factory, $container); $app->run(); -}); +})(); diff --git a/src/App/src/Middleware/AdminIndexMiddleware.php b/src/App/src/Middleware/AdminIndexMiddleware.php index 7d3e60f..514db74 100644 --- a/src/App/src/Middleware/AdminIndexMiddleware.php +++ b/src/App/src/Middleware/AdminIndexMiddleware.php @@ -10,10 +10,10 @@ use Dot\AnnotatedServices\Annotation\Inject; use Dot\AnnotatedServices\Annotation\Service; use Dot\Authentication\AuthenticationInterface; -use Interop\Http\ServerMiddleware\DelegateInterface; -use Interop\Http\ServerMiddleware\MiddlewareInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; use Zend\Diactoros\Response\RedirectResponse; use Zend\Expressive\Helper\UrlHelper; @@ -46,10 +46,10 @@ public function __construct(AuthenticationInterface $authentication, UrlHelper $ /** * @param ServerRequestInterface $request - * @param DelegateInterface $delegate + * @param RequestHandlerInterface $handler * @return ResponseInterface */ - public function process(ServerRequestInterface $request, DelegateInterface $delegate): ResponseInterface + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { //if root path is accessed and not authenticated send to login page //we do this to make interface more user-friendly, by bypassing the authorization guards @@ -61,6 +61,6 @@ public function process(ServerRequestInterface $request, DelegateInterface $dele } } - return $delegate->process($request); + return $handler->handle($request); } }