xref: /webtrees/app/Http/RequestHandlers/ModuleAction.php (revision a0801ffbb59d5bed474fc7a91bf1863ebca47791)
1*a0801ffbSGreg Roach<?php
2*a0801ffbSGreg Roach/**
3*a0801ffbSGreg Roach * webtrees: online genealogy
4*a0801ffbSGreg Roach * Copyright (C) 2019 webtrees development team
5*a0801ffbSGreg Roach * This program is free software: you can redistribute it and/or modify
6*a0801ffbSGreg Roach * it under the terms of the GNU General Public License as published by
7*a0801ffbSGreg Roach * the Free Software Foundation, either version 3 of the License, or
8*a0801ffbSGreg Roach * (at your option) any later version.
9*a0801ffbSGreg Roach * This program is distributed in the hope that it will be useful,
10*a0801ffbSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*a0801ffbSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*a0801ffbSGreg Roach * GNU General Public License for more details.
13*a0801ffbSGreg Roach * You should have received a copy of the GNU General Public License
14*a0801ffbSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
15*a0801ffbSGreg Roach */
16*a0801ffbSGreg Roachdeclare(strict_types=1);
17*a0801ffbSGreg Roach
18*a0801ffbSGreg Roachnamespace Fisharebest\Webtrees\Http\RequestHandlers;
19*a0801ffbSGreg Roach
20*a0801ffbSGreg Roachuse Fisharebest\Webtrees\Auth;
21*a0801ffbSGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface;
22*a0801ffbSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService;
23*a0801ffbSGreg Roachuse Psr\Http\Message\ResponseInterface;
24*a0801ffbSGreg Roachuse Psr\Http\Message\ServerRequestInterface;
25*a0801ffbSGreg Roachuse Psr\Http\Server\RequestHandlerInterface;
26*a0801ffbSGreg Roachuse Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
27*a0801ffbSGreg Roachuse Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
28*a0801ffbSGreg Roachuse function app;
29*a0801ffbSGreg Roachuse function method_exists;
30*a0801ffbSGreg Roachuse function strpos;
31*a0801ffbSGreg Roachuse function strtolower;
32*a0801ffbSGreg Roach
33*a0801ffbSGreg Roach/**
34*a0801ffbSGreg Roach * Controller for module actions.
35*a0801ffbSGreg Roach */
36*a0801ffbSGreg Roachclass ModuleAction implements RequestHandlerInterface
37*a0801ffbSGreg Roach{
38*a0801ffbSGreg Roach    /** @var ModuleService */
39*a0801ffbSGreg Roach    private $module_service;
40*a0801ffbSGreg Roach
41*a0801ffbSGreg Roach    /** @var UserInterface */
42*a0801ffbSGreg Roach    private $user;
43*a0801ffbSGreg Roach
44*a0801ffbSGreg Roach    /**
45*a0801ffbSGreg Roach     * ModuleController constructor.
46*a0801ffbSGreg Roach     *
47*a0801ffbSGreg Roach     * @param ModuleService $module_service
48*a0801ffbSGreg Roach     * @param UserInterface $user
49*a0801ffbSGreg Roach     */
50*a0801ffbSGreg Roach    public function __construct(ModuleService $module_service, UserInterface $user)
51*a0801ffbSGreg Roach    {
52*a0801ffbSGreg Roach        $this->module_service = $module_service;
53*a0801ffbSGreg Roach        $this->user           = $user;
54*a0801ffbSGreg Roach    }
55*a0801ffbSGreg Roach
56*a0801ffbSGreg Roach    /**
57*a0801ffbSGreg Roach     * Perform an HTTP action for one of the modules.
58*a0801ffbSGreg Roach     *
59*a0801ffbSGreg Roach     * @param ServerRequestInterface $request
60*a0801ffbSGreg Roach     *
61*a0801ffbSGreg Roach     * @return ResponseInterface
62*a0801ffbSGreg Roach     */
63*a0801ffbSGreg Roach    public function handle(ServerRequestInterface $request): ResponseInterface
64*a0801ffbSGreg Roach    {
65*a0801ffbSGreg Roach        $module_name = $request->getQueryParams()['module'] ?? $request->getParsedBody()['module'] ?? '';
66*a0801ffbSGreg Roach        $action      = $request->getQueryParams()['action'] ?? $request->getParsedBody()['action'] ?? '';
67*a0801ffbSGreg Roach
68*a0801ffbSGreg Roach        // Check that the module is enabled.
69*a0801ffbSGreg Roach        // The module itself will need to check any tree-level access,
70*a0801ffbSGreg Roach        // which may be different for each component (tab, menu, etc.) of the module.
71*a0801ffbSGreg Roach        $module = $this->module_service->findByName($module_name);
72*a0801ffbSGreg Roach
73*a0801ffbSGreg Roach        if ($module === null) {
74*a0801ffbSGreg Roach            throw new NotFoundHttpException('Module ' . $module_name . ' does not exist');
75*a0801ffbSGreg Roach        }
76*a0801ffbSGreg Roach
77*a0801ffbSGreg Roach        // We'll call a function such as Module::getFooBarAction()
78*a0801ffbSGreg Roach        $verb   = strtolower($request->getMethod());
79*a0801ffbSGreg Roach        $method = $verb . $action . 'Action';
80*a0801ffbSGreg Roach
81*a0801ffbSGreg Roach        // Actions with "Admin" in the name are for administrators only.
82*a0801ffbSGreg Roach        if (strpos($action, 'Admin') !== false && !Auth::isAdmin($this->user)) {
83*a0801ffbSGreg Roach            throw new AccessDeniedHttpException('Admin only action');
84*a0801ffbSGreg Roach        }
85*a0801ffbSGreg Roach
86*a0801ffbSGreg Roach        if (!method_exists($module, $method)) {
87*a0801ffbSGreg Roach            throw new NotFoundHttpException('Method ' . $method . '() not found in ' . $module_name);
88*a0801ffbSGreg Roach        }
89*a0801ffbSGreg Roach
90*a0801ffbSGreg Roach        return app()->dispatch($module, $method);
91*a0801ffbSGreg Roach    }
92*a0801ffbSGreg Roach}
93