xref: /webtrees/app/Module/AbstractModule.php (revision 16d6367af0fc87302889bd9d5831cab67c1a54f0)
1e2a378d3SGreg Roach<?php
2e2a378d3SGreg Roach/**
3e2a378d3SGreg Roach * webtrees: online genealogy
48fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team
5e2a378d3SGreg Roach * This program is free software: you can redistribute it and/or modify
6e2a378d3SGreg Roach * it under the terms of the GNU General Public License as published by
7e2a378d3SGreg Roach * the Free Software Foundation, either version 3 of the License, or
8e2a378d3SGreg Roach * (at your option) any later version.
9e2a378d3SGreg Roach * This program is distributed in the hope that it will be useful,
10e2a378d3SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
11e2a378d3SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12e2a378d3SGreg Roach * GNU General Public License for more details.
13e2a378d3SGreg Roach * You should have received a copy of the GNU General Public License
14e2a378d3SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
15e2a378d3SGreg Roach */
16e7f56f2aSGreg Roachdeclare(strict_types=1);
17e7f56f2aSGreg Roach
1876692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module;
1976692c8bSGreg Roach
200e62c4b8SGreg Roachuse Fisharebest\Webtrees\Auth;
210e62c4b8SGreg Roachuse Fisharebest\Webtrees\Database;
220e62c4b8SGreg Roachuse Fisharebest\Webtrees\Tree;
233f412448SGreg Roachuse Illuminate\Database\Capsule\Manager as DB;
24e2ae4578SGreg Roachuse Symfony\Component\HttpFoundation\Response;
25e2a378d3SGreg Roach
26e2a378d3SGreg Roach/**
27e2a378d3SGreg Roach * Class AbstractModule - common functions for blocks
28e2a378d3SGreg Roach */
29c1010edaSGreg Roachabstract class AbstractModule
30c1010edaSGreg Roach{
31e2a378d3SGreg Roach    /** @var string The directory where the module is installed */
32e2a378d3SGreg Roach    private $directory;
33e2a378d3SGreg Roach
34e2a378d3SGreg Roach    /** @var string[] A cached copy of the module settings */
35e2a378d3SGreg Roach    private $settings;
36e2a378d3SGreg Roach
3787503df0SGreg Roach    /** @var string For custom modules - optional (recommended) version number */
38*16d6367aSGreg Roach    public const CUSTOM_VERSION = '';
3987503df0SGreg Roach
4087503df0SGreg Roach    /** @var string For custom modules - link for support, upgrades, etc. */
41*16d6367aSGreg Roach    public const CUSTOM_WEBSITE = '';
4287503df0SGreg Roach
43e2ae4578SGreg Roach    protected $layout = 'layouts/default';
44e2ae4578SGreg Roach
45e2a378d3SGreg Roach    /**
46e2a378d3SGreg Roach     * Create a new module.
47e2a378d3SGreg Roach     *
48e2a378d3SGreg Roach     * @param string $directory Where is this module installed
49e2a378d3SGreg Roach     */
50027c6af4SGreg Roach    public function __construct(string $directory)
51c1010edaSGreg Roach    {
52e2a378d3SGreg Roach        $this->directory = $directory;
53e2a378d3SGreg Roach    }
54e2a378d3SGreg Roach
55e2a378d3SGreg Roach    /**
5676692c8bSGreg Roach     * Get a block setting.
5776692c8bSGreg Roach     *
58cbc1590aSGreg Roach     * @param int    $block_id
59e2a378d3SGreg Roach     * @param string $setting_name
6072ac996dSGreg Roach     * @param string $default_value
61e2a378d3SGreg Roach     *
6272ac996dSGreg Roach     * @return string
63e2a378d3SGreg Roach     */
64acf76a54SGreg Roach    public function getBlockSetting(int $block_id, string $setting_name, string $default_value = ''): string
65c1010edaSGreg Roach    {
66e2a378d3SGreg Roach        $setting_value = Database::prepare(
67e5588fb0SGreg Roach            "SELECT setting_value FROM `##block_setting` WHERE block_id = :block_id AND setting_name = :setting_name"
6813abd6f3SGreg Roach        )->execute([
69e2a378d3SGreg Roach            'block_id'     => $block_id,
70e2a378d3SGreg Roach            'setting_name' => $setting_name,
7113abd6f3SGreg Roach        ])->fetchOne();
72e2a378d3SGreg Roach
7325c4634fSRico Sonntag        return $setting_value ?? $default_value;
74e2a378d3SGreg Roach    }
75e2a378d3SGreg Roach
76e2a378d3SGreg Roach    /**
7776692c8bSGreg Roach     * Set a block setting.
7876692c8bSGreg Roach     *
79cbc1590aSGreg Roach     * @param int    $block_id
80e2a378d3SGreg Roach     * @param string $setting_name
8120ac4041SGreg Roach     * @param string $setting_value
82e2a378d3SGreg Roach     *
83e2a378d3SGreg Roach     * @return $this
84e2a378d3SGreg Roach     */
858f53f488SRico Sonntag    public function setBlockSetting(int $block_id, string $setting_name, string $setting_value): self
86c1010edaSGreg Roach    {
87e2a378d3SGreg Roach        Database::prepare(
88e2a378d3SGreg Roach            "REPLACE INTO `##block_setting` (block_id, setting_name, setting_value) VALUES (:block_id, :setting_name, :setting_value)"
8913abd6f3SGreg Roach        )->execute([
90e2a378d3SGreg Roach            'block_id'      => $block_id,
91e2a378d3SGreg Roach            'setting_name'  => $setting_name,
92e2a378d3SGreg Roach            'setting_value' => $setting_value,
9313abd6f3SGreg Roach        ]);
94e2a378d3SGreg Roach
95e2a378d3SGreg Roach        return $this;
96e2a378d3SGreg Roach    }
97e2a378d3SGreg Roach
98e2a378d3SGreg Roach    /**
99e2a378d3SGreg Roach     * What is the default access level for this module?
100e2a378d3SGreg Roach     *
101e2a378d3SGreg Roach     * Some modules are aimed at admins or managers, and are not generally shown to users.
102e2a378d3SGreg Roach     *
103cbc1590aSGreg Roach     * @return int
104e2a378d3SGreg Roach     */
1058f53f488SRico Sonntag    public function defaultAccessLevel(): int
106c1010edaSGreg Roach    {
107e2a378d3SGreg Roach        // Returns one of: Auth::PRIV_HIDE, Auth::PRIV_PRIVATE, Auth::PRIV_USER, WT_PRIV_ADMIN
108e2a378d3SGreg Roach        return Auth::PRIV_PRIVATE;
109e2a378d3SGreg Roach    }
110e2a378d3SGreg Roach
111e2a378d3SGreg Roach    /**
112e2a378d3SGreg Roach     * Provide a unique internal name for this module
113e2a378d3SGreg Roach     *
114e2a378d3SGreg Roach     * @return string
115e2a378d3SGreg Roach     */
1168f53f488SRico Sonntag    public function getName(): string
117c1010edaSGreg Roach    {
118e2a378d3SGreg Roach        return basename($this->directory);
119e2a378d3SGreg Roach    }
120e2a378d3SGreg Roach
121e2a378d3SGreg Roach    /**
122e2a378d3SGreg Roach     * Load all the settings for the module into a cache.
123e2a378d3SGreg Roach     *
124e2a378d3SGreg Roach     * Since modules may have many settings, and will probably want to use
125e2a378d3SGreg Roach     * lots of them, load them all at once and cache them.
12618d7a90dSGreg Roach     *
12718d7a90dSGreg Roach     * @return void
128e2a378d3SGreg Roach     */
129c1010edaSGreg Roach    private function loadAllSettings()
130c1010edaSGreg Roach    {
131e2a378d3SGreg Roach        if ($this->settings === null) {
1323f412448SGreg Roach            $this->settings = DB::table('module_setting')
1333f412448SGreg Roach                ->where('module_name', '=', $this->getName())
1343f412448SGreg Roach                ->pluck('setting_value', 'setting_name')
1353f412448SGreg Roach                ->all();
136e2a378d3SGreg Roach        }
137e2a378d3SGreg Roach    }
138e2a378d3SGreg Roach
139e2a378d3SGreg Roach    /**
140e2a378d3SGreg Roach     * Get a module setting. Return a default if the setting is not set.
141e2a378d3SGreg Roach     *
142e2a378d3SGreg Roach     * @param string $setting_name
143e2a378d3SGreg Roach     * @param string $default
144e2a378d3SGreg Roach     *
14515d603e7SGreg Roach     * @return string
146e2a378d3SGreg Roach     */
147c1010edaSGreg Roach    public function getPreference($setting_name, $default = '')
148c1010edaSGreg Roach    {
149e2a378d3SGreg Roach        $this->loadAllSettings();
150e2a378d3SGreg Roach
151e2a378d3SGreg Roach        if (array_key_exists($setting_name, $this->settings)) {
152e2a378d3SGreg Roach            return $this->settings[$setting_name];
153e2a378d3SGreg Roach        }
154b2ce94c6SRico Sonntag
155b2ce94c6SRico Sonntag        return $default;
156e2a378d3SGreg Roach    }
157e2a378d3SGreg Roach
158e2a378d3SGreg Roach    /**
159e2a378d3SGreg Roach     * Set a module setting.
160e2a378d3SGreg Roach     *
161e2a378d3SGreg Roach     * Since module settings are NOT NULL, setting a value to NULL will cause
162e2a378d3SGreg Roach     * it to be deleted.
163e2a378d3SGreg Roach     *
164e2a378d3SGreg Roach     * @param string $setting_name
165e2a378d3SGreg Roach     * @param string $setting_value
16615d603e7SGreg Roach     *
16715d603e7SGreg Roach     * @return $this
168e2a378d3SGreg Roach     */
1698f53f488SRico Sonntag    public function setPreference($setting_name, $setting_value): self
170c1010edaSGreg Roach    {
171e2a378d3SGreg Roach        $this->loadAllSettings();
172e2a378d3SGreg Roach
173b7ee5e66SCarmen Pijpers        if (!array_key_exists($setting_name, $this->settings)) {
174b7ee5e66SCarmen Pijpers            Database::prepare(
175b7ee5e66SCarmen Pijpers                "INSERT INTO `##module_setting` (module_name, setting_name, setting_value) VALUES (?, ?, ?)"
176c1010edaSGreg Roach            )->execute([
177c1010edaSGreg Roach                $this->getName(),
178c1010edaSGreg Roach                $setting_name,
179c1010edaSGreg Roach                $setting_value,
180c1010edaSGreg Roach            ]);
181b7ee5e66SCarmen Pijpers
182b7ee5e66SCarmen Pijpers            $this->settings[$setting_name] = $setting_value;
183b7ee5e66SCarmen Pijpers        } elseif ($setting_value !== $this->getPreference($setting_name)) {
184e2a378d3SGreg Roach            Database::prepare(
185e2a378d3SGreg Roach                "UPDATE `##module_setting` SET setting_value = ? WHERE module_name = ? AND setting_name = ?"
186c1010edaSGreg Roach            )->execute([
187c1010edaSGreg Roach                $setting_value,
188c1010edaSGreg Roach                $this->getName(),
189c1010edaSGreg Roach                $setting_name,
190c1010edaSGreg Roach            ]);
19115d603e7SGreg Roach
192e2a378d3SGreg Roach            $this->settings[$setting_name] = $setting_value;
193e2a378d3SGreg Roach        }
19415d603e7SGreg Roach
19515d603e7SGreg Roach        return $this;
196e2a378d3SGreg Roach    }
197e2a378d3SGreg Roach
198e2a378d3SGreg Roach    /**
199e2a378d3SGreg Roach     * Get a the current access level for a module
200e2a378d3SGreg Roach     *
201e2a378d3SGreg Roach     * @param Tree   $tree
202cbc1590aSGreg Roach     * @param string $component tab, block, menu, etc
203e2a378d3SGreg Roach     *
204cbc1590aSGreg Roach     * @return int
205e2a378d3SGreg Roach     */
206c1010edaSGreg Roach    public function getAccessLevel(Tree $tree, $component)
207c1010edaSGreg Roach    {
208e2a378d3SGreg Roach        $access_level = Database::prepare(
209e2a378d3SGreg Roach            "SELECT access_level FROM `##module_privacy` WHERE gedcom_id = :gedcom_id AND module_name = :module_name AND component = :component"
21013abd6f3SGreg Roach        )->execute([
21172cf66d4SGreg Roach            'gedcom_id'   => $tree->id(),
212e2a378d3SGreg Roach            'module_name' => $this->getName(),
213e2a378d3SGreg Roach            'component'   => $component,
21413abd6f3SGreg Roach        ])->fetchOne();
215e2a378d3SGreg Roach
216e2a378d3SGreg Roach        if ($access_level === null) {
217e2a378d3SGreg Roach            return $this->defaultAccessLevel();
218e2a378d3SGreg Roach        }
219b2ce94c6SRico Sonntag
220b2ce94c6SRico Sonntag        return (int) $access_level;
221e2a378d3SGreg Roach    }
222e2ae4578SGreg Roach
223e2ae4578SGreg Roach    /**
224e2ae4578SGreg Roach     * Create a response object from a view.
225e2ae4578SGreg Roach     *
226e2ae4578SGreg Roach     * @param string  $view_name
227e2ae4578SGreg Roach     * @param mixed[] $view_data
228e2ae4578SGreg Roach     * @param int     $status
229e2ae4578SGreg Roach     *
230e2ae4578SGreg Roach     * @return Response
231e2ae4578SGreg Roach     */
232c1010edaSGreg Roach    protected function viewResponse($view_name, $view_data, $status = Response::HTTP_OK): Response
233c1010edaSGreg Roach    {
234e2ae4578SGreg Roach        // Make the view's data available to the layout.
235e2ae4578SGreg Roach        $layout_data = $view_data;
236e2ae4578SGreg Roach
237e2ae4578SGreg Roach        // Render the view
238e2ae4578SGreg Roach        $layout_data['content'] = view($view_name, $view_data);
239e2ae4578SGreg Roach
240e2ae4578SGreg Roach        // Insert the view into the layout
241e2ae4578SGreg Roach        $html = view($this->layout, $layout_data);
242e2ae4578SGreg Roach
243e2ae4578SGreg Roach        return new Response($html, $status);
244e2ae4578SGreg Roach    }
245e2a378d3SGreg Roach}
246