Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
97.30% |
36 / 37 |
|
83.33% |
5 / 6 |
CRAP | |
0.00% |
0 / 1 |
| HtmxCommentsRouteHandler | |
97.22% |
35 / 36 |
|
83.33% |
5 / 6 |
21 | |
0.00% |
0 / 1 |
| __construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| handle | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
| handleMentionsRoute | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
| resolveMentionsResponse | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
4 | |||
| handleCommentCrud | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
4.05 | |||
| handleCommentModification | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
7 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | /** @license For full copyright and license information, please see the LICENSE.md file. */ |
| 6 | |
| 7 | namespace App\Core\Bootstrap\Dispatcher\Handler; |
| 8 | |
| 9 | defined('AMMONLY_APP') || exit('Direct script access is forbidden.'); |
| 10 | |
| 11 | use App\Core\Engine\Application\Security\PermissionContextFactory; |
| 12 | use App\Core\Engine\Domain\Model\PermissionContext; |
| 13 | use App\Modules\Comments\Presentation\Htmx\CommentsHtmxController; |
| 14 | use App\Modules\Comments\Presentation\Htmx\MentionsHtmxController; |
| 15 | use Nyholm\Psr7\Factory\Psr17Factory; |
| 16 | use Psr\Http\Message\ResponseInterface; |
| 17 | use Psr\Http\Message\ServerRequestInterface; |
| 18 | use Psr\Http\Server\RequestHandlerInterface; |
| 19 | |
| 20 | final readonly class HtmxCommentsRouteHandler implements RequestHandlerInterface |
| 21 | { |
| 22 | public function __construct( |
| 23 | private ?CommentsHtmxController $ctrl, |
| 24 | private ?MentionsHtmxController $mentionsCtrl, |
| 25 | private string $path, |
| 26 | private Psr17Factory $psr17, |
| 27 | private PermissionContextFactory $contextFactory |
| 28 | ) { |
| 29 | } |
| 30 | |
| 31 | public function handle(ServerRequestInterface $request): ResponseInterface |
| 32 | { |
| 33 | if (str_starts_with($this->path, '/htmx/comments/mentions')) { |
| 34 | return $this->handleMentionsRoute($request); |
| 35 | } |
| 36 | if ($this->ctrl === null) { |
| 37 | return $this->psr17->createResponse(404); |
| 38 | } |
| 39 | $res = $this->handleCommentCrud($request) ?? $this->handleCommentModification($request); |
| 40 | return $res ?? $this->psr17->createResponse(404); |
| 41 | } |
| 42 | |
| 43 | private function handleMentionsRoute(ServerRequestInterface $req): ResponseInterface |
| 44 | { |
| 45 | if ($this->mentionsCtrl === null) { |
| 46 | return $this->psr17->createResponse(404); |
| 47 | } |
| 48 | $ctx = $this->contextFactory->createFromRequest($req); |
| 49 | $res = $this->resolveMentionsResponse($req, $ctx); |
| 50 | return $res ?? $this->psr17->createResponse(404); |
| 51 | } |
| 52 | |
| 53 | private function resolveMentionsResponse( |
| 54 | ServerRequestInterface $req, |
| 55 | PermissionContext $ctx |
| 56 | ): ?ResponseInterface { |
| 57 | if ($this->path === '/htmx/comments/mentions') { |
| 58 | return $this->mentionsCtrl->actionList($req, $ctx); |
| 59 | } |
| 60 | if ($this->path === '/htmx/comments/mentions/mark-all-read') { |
| 61 | return $this->mentionsCtrl->actionMarkAllRead($req, $ctx); |
| 62 | } |
| 63 | return preg_match('#^/htmx/comments/mentions/(\d+)/mark-read$#', $this->path, $m) |
| 64 | ? $this->mentionsCtrl->actionMarkRead($req, (int) $m[1], $ctx) |
| 65 | : null; |
| 66 | } |
| 67 | |
| 68 | private function handleCommentCrud(ServerRequestInterface $req): ?ResponseInterface |
| 69 | { |
| 70 | if ($this->path === '/htmx/comments/autocomplete') { |
| 71 | return $this->ctrl->actionAutocomplete($req); |
| 72 | } |
| 73 | if (preg_match('#^/htmx/comments/([a-zA-Z0-9_-]+)/(\d+)$#', $this->path, $m)) { |
| 74 | return $req->getMethod() === 'POST' |
| 75 | ? $this->ctrl->actionCreate($req, $m[1], (int) $m[2]) |
| 76 | : $this->ctrl->actionStream($req, $m[1], (int) $m[2]); |
| 77 | } |
| 78 | return null; |
| 79 | } |
| 80 | |
| 81 | private function handleCommentModification(ServerRequestInterface $req): ?ResponseInterface |
| 82 | { |
| 83 | if ( |
| 84 | preg_match('#^/htmx/comments/(\d+)/toggle-pin$#', $this->path, $m) |
| 85 | && $req->getMethod() === 'POST' |
| 86 | ) { |
| 87 | return $this->ctrl->actionTogglePin($req, (int) $m[1]); |
| 88 | } |
| 89 | if ( |
| 90 | preg_match('#^/htmx/comments/(\d+)/toggle-verify$#', $this->path, $m) |
| 91 | && $req->getMethod() === 'POST' |
| 92 | ) { |
| 93 | return $this->ctrl->actionToggleVerify($req, (int) $m[1]); |
| 94 | } |
| 95 | return ( |
| 96 | preg_match('#^/htmx/comments/(\d+)(?:/delete)?$#', $this->path, $m) |
| 97 | && in_array($req->getMethod(), ['DELETE', 'POST'], true) |
| 98 | ) ? $this->ctrl->actionDelete($req, (int) $m[1]) : null; |
| 99 | } |
| 100 | } |