1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2019 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16namespace Fisharebest\Webtrees;
17
18use Fisharebest\Webtrees\Controller\PageController;
19use Fisharebest\Webtrees\Functions\FunctionsEdit;
20use Fisharebest\Webtrees\Module\AbstractModule;
21use Fisharebest\Webtrees\Module\ModuleBlockInterface;
22use Fisharebest\Webtrees\Module\ModuleChartInterface;
23use Fisharebest\Webtrees\Module\ModuleConfigInterface;
24use Fisharebest\Webtrees\Module\ModuleMenuInterface;
25use Fisharebest\Webtrees\Module\ModuleReportInterface;
26use Fisharebest\Webtrees\Module\ModuleSidebarInterface;
27use Fisharebest\Webtrees\Module\ModuleTabInterface;
28use Fisharebest\Webtrees\Module\ModuleThemeInterface;
29
30define('WT_SCRIPT_NAME', 'admin_modules.php');
31require 'includes/session.php';
32
33$controller = new PageController;
34$controller
35    ->restrictAccess(Auth::isAdmin())
36    ->setPageTitle(I18N::translate('Module administration'));
37
38$modules       = Module::getInstalledModules('disabled');
39$module_status = Database::prepare("SELECT module_name, status FROM `##module`")->fetchAssoc();
40
41uasort($modules, function (AbstractModule $x, AbstractModule $y) {
42    return I18N::strcasecmp($x->getTitle(), $y->getTitle());
43});
44
45if (Filter::post('action') === 'update_mods' && Filter::checkCsrf()) {
46    foreach ($modules as $module) {
47        $new_status = Filter::post('status-' . $module->getName(), '[01]');
48        if ($new_status !== null) {
49            $new_status = $new_status ? 'enabled' : 'disabled';
50            $old_status = $module_status[$module->getName()];
51            if ($new_status !== $old_status) {
52                Database::prepare("UPDATE `##module` SET status=? WHERE module_name=?")->execute(array($new_status, $module->getName()));
53                if ($new_status === 'disabled') {
54                    FlashMessages::addMessage(I18N::translate('The module “%s” has been disabled.', $module->getTitle()), 'success');
55                } else {
56                    FlashMessages::addMessage(I18N::translate('The module “%s” has been enabled.', $module->getTitle()), 'success');
57                }
58            }
59        }
60    }
61
62    header('Location: ' . WT_BASE_URL . 'admin_modules.php');
63
64    return;
65}
66
67if (Filter::post('action') === 'delete' && Filter::checkCsrf()) {
68    $module_name = Filter::post('module_name');
69    Database::prepare(
70        "DELETE `##block_setting`" .
71        " FROM `##block_setting`" .
72        " JOIN `##block` USING (block_id)" .
73        " JOIN `##module` USING (module_name)" .
74        " WHERE module_name=?"
75    )->execute(array($module_name));
76    Database::prepare(
77        "DELETE `##block`" .
78        " FROM `##block`" .
79        " JOIN `##module` USING (module_name)" .
80        " WHERE module_name=?"
81    )->execute(array($module_name));
82    Database::prepare("DELETE FROM `##module_setting` WHERE module_name=?")->execute(array($module_name));
83    Database::prepare("DELETE FROM `##module_privacy` WHERE module_name=?")->execute(array($module_name));
84    Database::prepare("DELETE FROM `##module` WHERE module_name=?")->execute(array($module_name));
85
86    FlashMessages::addMessage(I18N::translate('The preferences for the module “%s” have been deleted.', $module_name), 'success');
87
88    header('Location: ' . WT_BASE_URL . 'admin_modules.php');
89
90    return;
91}
92
93// The module can’t be found on disk?
94// Don't delete it automatically. It may be temporarily missing, after a re-installation, etc.
95foreach ($module_status as $module_name => $status) {
96    if (!array_key_exists($module_name, $modules)) {
97        $html =
98            I18N::translate('Preferences exist for the module “%s”, but this module no longer exists.', '<span dir="ltr">' . $module_name . '</span>') .
99            '<form method="post" class="form-inline">' .
100            Filter::getCsrf() .
101            '<input type="hidden" name="action" value="delete">' .
102            '<input type="hidden" name="module_name" value="' . $module_name . '">' .
103            '<button type="submit" class="btn btn-link">' . I18N::translate('Delete the preferences for this module.') . '</button>' .
104            '</form>';
105        FlashMessages::addMessage($html, 'warning');
106    }
107}
108
109$controller
110    ->pageHeader()
111    ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL)
112    ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL)
113    ->addInlineJavascript('
114		function reindexMods(id) {
115			jQuery("#" + id + " input").each(
116				function (index, value) {
117					value.value = index+1;
118				});
119		}
120		jQuery("#installed_table").dataTable( {
121			paging: false,
122			' . I18N::datatablesI18N() . ',
123			sorting: [[ 1, "asc" ]],
124			columns : [
125				{ sortable: false, class: "center" },
126				null,
127				null,
128				{ class: "center" },
129				{ class: "center" },
130				{ class: "center" },
131				{ class: "center" },
132				{ class: "center" },
133				{ class: "center" },
134				{ class: "center", visible: false } // The Module system does not yet include themes
135			]
136		});
137	');
138
139?>
140<ol class="breadcrumb small">
141    <li><a href="admin.php"><?php echo I18N::translate('Control panel'); ?></a></li>
142    <li class="active"><?php echo $controller->getPageTitle(); ?></li>
143</ol>
144
145<h1><?php echo $controller->getPageTitle(); ?></h1>
146
147<form method="post" action="<?php echo WT_SCRIPT_NAME; ?>">
148    <input type="hidden" name="action" value="update_mods">
149    <?php echo Filter::getCsrf(); ?>
150    <table class="table table-bordered table-hover table-condensed table-module-administration">
151        <caption class="sr-only">
152            <?php echo I18N::translate('Module administration'); ?>
153        </caption>
154        <thead>
155        <tr>
156            <th><?php echo I18N::translate('Enabled'); ?></th>
157            <th><?php echo I18N::translate('Module'); ?></th>
158            <th><?php echo I18N::translate('Description'); ?></th>
159            <th class="hidden-xs"><a href="admin_module_menus.php"><?php echo I18N::translate('Menus'); ?></a></th>
160            <th class="hidden-xs"><a href="admin_module_tabs.php"><?php echo I18N::translate('Tabs'); ?></a></th>
161            <th class="hidden-xs"><a href="admin_module_sidebar.php"><?php echo I18N::translate('Sidebars'); ?></a></th>
162            <th class="hidden-xs"><a href="admin_module_blocks.php"><?php echo I18N::translate('Blocks'); ?></a></th>
163            <th class="hidden-xs"><a href="admin_module_charts.php"><?php echo I18N::translate('Charts'); ?></a></th>
164            <th class="hidden-xs"><a href="admin_module_reports.php"><?php echo I18N::translate('Reports'); ?></a></th>
165            <th class="hidden"><?php echo I18N::translate('Themes'); ?></th>
166        </tr>
167        </thead>
168        <tbody>
169            <?php foreach ($modules as $module_name => $module): ?>
170                <tr>
171                    <td class="text-center">
172                        <?php echo FunctionsEdit::twoStateCheckbox('status-' . $module->getName(), $module_status[$module_name] === 'enabled') ?>
173                    </td>
174                    <td>
175                        <?php if ($module instanceof ModuleConfigInterface): ?>
176                            <a href="<?php echo $module->getConfigLink() ?>">
177                                <?php echo $module->getTitle() ?> <i class="fa fa-cogs"></i>
178                            </a>
179                        <?php else: ?>
180                            <?php echo $module->getTitle() ?>
181                        <?php endif; ?>
182                        <?php if (!in_array($module->getName(), Module::getCoreModuleNames())): ?>
183                            <br>
184                        <?php endif; ?>
185                    </td>
186                    <td>
187                        <?php echo '', $module->getDescription() ?>
188                        <?php if (!in_array($module->getName(), Module::getCoreModuleNames())): ?>
189                            <br>
190                            <i class="fa fa-asterisk"></i>
191                            <?php echo I18N::translate('Custom module') ?>
192                            <?php if ($module::CUSTOM_VERSION): ?>
193                                - <?php echo I18N::translate('Version') ?> <?php echo $module::CUSTOM_VERSION ?>
194                            <?php endif; ?>
195                            <?php if ($module::CUSTOM_WEBSITE): ?>
196                                - <a href="<?php echo $module::CUSTOM_WEBSITE ?>">
197                                    <?php echo $module::CUSTOM_WEBSITE ?>
198                                </a>
199                            <?php endif; ?>
200                        <?php endif; ?>
201                    </td>
202                    <td class="text-center text-muted hidden-xs">
203                        <?php if ($module instanceof ModuleMenuInterface): ?>
204                            <i class="fa fa-list-ul" title="<?php echo I18N::translate('Menu') ?>"></i>
205                        <?php else: ?>
206                            -
207                        <?php endif; ?>
208                    </td>
209                    <td class="text-center text-muted hidden-xs">
210                        <?php if ($module instanceof ModuleTabInterface): ?>
211                            <i class="fa fa-folder" title="<?php echo I18N::translate('Tab') ?>"></i>
212                        <?php else: ?>
213                            -
214                        <?php endif; ?>
215                    </td>
216                    <td class="text-center text-muted hidden-xs">
217                        <?php if ($module instanceof ModuleSidebarInterface): ?>
218                            <i class="fa fa-th-large" title="<?php echo I18N::translate('Sidebar') ?>"></i>
219                        <?php else: ?>
220                            -
221                        <?php endif; ?>
222                    </td>
223                    <td class="text-center text-muted hidden-xs">
224                        <?php if ($module instanceof ModuleBlockInterface): ?>
225                            <?php if ($module->isUserBlock()): ?>
226                                <i class="fa fa-user" title="<?php echo I18N::translate('My page') ?>"></i>
227                            <?php endif; ?>
228                            <?php if ($module->isUserBlock()): ?>
229                                <i class="fa fa-tree" title="<?php echo I18N::translate('Home page') ?>"></i>
230                            <?php endif; ?>
231                        <?php else: ?>
232                            -
233                        <?php endif; ?>
234                    </td>
235                    <td class="text-center text-muted hidden-xs">
236                        <?php if ($module instanceof ModuleChartInterface): ?>
237                            <i class="fa fa-share-alt" title="<?php echo I18N::translate('Chart') ?>"></i>
238                        <?php else: ?>
239                            -
240                        <?php endif; ?>
241                    </td>
242                    <td class="text-center text-muted hidden-xs">
243                        <?php if ($module instanceof ModuleReportInterface): ?>
244                            <i class="fa fa-file" title="<?php echo I18N::translate('Report') ?>"></i>
245                        <?php else: ?>
246                            -
247                        <?php endif; ?>
248                    </td>
249                    <td class="text-center text-muted hidden">
250                        <?php if ($module instanceof ModuleThemeInterface): ?>
251                            <i class="fa fa-check" title="<?php echo I18N::translate('Theme') ?>"></i>
252                        <?php else: ?>
253                            -
254                        <?php endif; ?>
255                    </td>
256                </tr>
257            <?php endforeach; ?>
258        </tbody>
259    </table>
260    <button class="btn btn-primary" type="submit">
261        <i class="fa fa-check"></i>
262        <?php echo I18N::translate('save'); ?></button>
263</form>
264