xref: /webtrees/app/Http/RequestHandlers/ControlPanel.php (revision 0c0910bf0f275a14f35d2ccdf698f91f79e269d4)
1*0c0910bfSGreg Roach<?php
2*0c0910bfSGreg Roach
3*0c0910bfSGreg Roach/**
4*0c0910bfSGreg Roach * webtrees: online genealogy
5*0c0910bfSGreg Roach * Copyright (C) 2019 webtrees development team
6*0c0910bfSGreg Roach * This program is free software: you can redistribute it and/or modify
7*0c0910bfSGreg Roach * it under the terms of the GNU General Public License as published by
8*0c0910bfSGreg Roach * the Free Software Foundation, either version 3 of the License, or
9*0c0910bfSGreg Roach * (at your option) any later version.
10*0c0910bfSGreg Roach * This program is distributed in the hope that it will be useful,
11*0c0910bfSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*0c0910bfSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*0c0910bfSGreg Roach * GNU General Public License for more details.
14*0c0910bfSGreg Roach * You should have received a copy of the GNU General Public License
15*0c0910bfSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
16*0c0910bfSGreg Roach */
17*0c0910bfSGreg Roachdeclare(strict_types=1);
18*0c0910bfSGreg Roach
19*0c0910bfSGreg Roachnamespace Fisharebest\Webtrees\Http\RequestHandlers;
20*0c0910bfSGreg Roach
21*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Http\ViewResponseTrait;
22*0c0910bfSGreg Roachuse Fisharebest\Webtrees\I18N;
23*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\FamilyListModule;
24*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\IndividualListModule;
25*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\MediaListModule;
26*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleAnalyticsInterface;
27*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleBlockInterface;
28*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleChartInterface;
29*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleFooterInterface;
30*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleHistoricEventsInterface;
31*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleLanguageInterface;
32*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleListInterface;
33*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleMenuInterface;
34*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleReportInterface;
35*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleSidebarInterface;
36*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleTabInterface;
37*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\ModuleThemeInterface;
38*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\NoteListModule;
39*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\RepositoryListModule;
40*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Module\SourceListModule;
41*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\HousekeepingService;
42*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\ModuleService;
43*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\ServerCheckService;
44*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\TreeService;
45*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\UpgradeService;
46*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Services\UserService;
47*0c0910bfSGreg Roachuse Fisharebest\Webtrees\Webtrees;
48*0c0910bfSGreg Roachuse Illuminate\Database\Capsule\Manager as DB;
49*0c0910bfSGreg Roachuse Illuminate\Database\Query\Expression;
50*0c0910bfSGreg Roachuse Illuminate\Database\Query\JoinClause;
51*0c0910bfSGreg Roachuse Illuminate\Support\Collection;
52*0c0910bfSGreg Roachuse League\Flysystem\Adapter\Local;
53*0c0910bfSGreg Roachuse League\Flysystem\Filesystem;
54*0c0910bfSGreg Roachuse Psr\Http\Message\ResponseInterface;
55*0c0910bfSGreg Roachuse Psr\Http\Message\ServerRequestInterface;
56*0c0910bfSGreg Roachuse Psr\Http\Server\RequestHandlerInterface;
57*0c0910bfSGreg Roach
58*0c0910bfSGreg Roach/**
59*0c0910bfSGreg Roach * The control panel shows a summary of the site and links to admin functions.
60*0c0910bfSGreg Roach */
61*0c0910bfSGreg Roachclass ControlPanel implements RequestHandlerInterface
62*0c0910bfSGreg Roach{
63*0c0910bfSGreg Roach    use ViewResponseTrait;
64*0c0910bfSGreg Roach
65*0c0910bfSGreg Roach    /** @var ModuleService */
66*0c0910bfSGreg Roach    private $module_service;
67*0c0910bfSGreg Roach
68*0c0910bfSGreg Roach    /** @var HousekeepingService */
69*0c0910bfSGreg Roach    private $housekeeping_service;
70*0c0910bfSGreg Roach
71*0c0910bfSGreg Roach    /** @var ServerCheckService */
72*0c0910bfSGreg Roach    private $server_check_service;
73*0c0910bfSGreg Roach
74*0c0910bfSGreg Roach    /** @var TreeService */
75*0c0910bfSGreg Roach    private $tree_service;
76*0c0910bfSGreg Roach
77*0c0910bfSGreg Roach    /** @var UpgradeService */
78*0c0910bfSGreg Roach    private $upgrade_service;
79*0c0910bfSGreg Roach
80*0c0910bfSGreg Roach    /** @var UserService */
81*0c0910bfSGreg Roach    private $user_service;
82*0c0910bfSGreg Roach
83*0c0910bfSGreg Roach    /**
84*0c0910bfSGreg Roach     * ControlPanel constructor.
85*0c0910bfSGreg Roach     *
86*0c0910bfSGreg Roach     * @param HousekeepingService $housekeeping_service
87*0c0910bfSGreg Roach     * @param ModuleService       $module_service
88*0c0910bfSGreg Roach     * @param ServerCheckService  $server_check_service
89*0c0910bfSGreg Roach     * @param TreeService         $tree_service
90*0c0910bfSGreg Roach     * @param UpgradeService      $upgrade_service
91*0c0910bfSGreg Roach     * @param UserService         $user_service
92*0c0910bfSGreg Roach     */
93*0c0910bfSGreg Roach    public function __construct(
94*0c0910bfSGreg Roach        HousekeepingService $housekeeping_service,
95*0c0910bfSGreg Roach        ModuleService $module_service,
96*0c0910bfSGreg Roach        ServerCheckService $server_check_service,
97*0c0910bfSGreg Roach        TreeService $tree_service,
98*0c0910bfSGreg Roach        UpgradeService $upgrade_service,
99*0c0910bfSGreg Roach        UserService $user_service
100*0c0910bfSGreg Roach    ) {
101*0c0910bfSGreg Roach        $this->module_service       = $module_service;
102*0c0910bfSGreg Roach        $this->housekeeping_service = $housekeeping_service;
103*0c0910bfSGreg Roach        $this->server_check_service = $server_check_service;
104*0c0910bfSGreg Roach        $this->tree_service         = $tree_service;
105*0c0910bfSGreg Roach        $this->upgrade_service      = $upgrade_service;
106*0c0910bfSGreg Roach        $this->user_service         = $user_service;
107*0c0910bfSGreg Roach    }
108*0c0910bfSGreg Roach
109*0c0910bfSGreg Roach    /**
110*0c0910bfSGreg Roach     * @param ServerRequestInterface $request
111*0c0910bfSGreg Roach     *
112*0c0910bfSGreg Roach     * @return ResponseInterface
113*0c0910bfSGreg Roach     */
114*0c0910bfSGreg Roach    public function handle(ServerRequestInterface $request): ResponseInterface
115*0c0910bfSGreg Roach    {
116*0c0910bfSGreg Roach        $this->layout = 'layouts/administration';
117*0c0910bfSGreg Roach
118*0c0910bfSGreg Roach        $filesystem      = new Filesystem(new Local(Webtrees::ROOT_DIR));
119*0c0910bfSGreg Roach        $files_to_delete = $this->housekeeping_service->deleteOldWebtreesFiles($filesystem);
120*0c0910bfSGreg Roach
121*0c0910bfSGreg Roach        return $this->viewResponse('admin/control-panel', [
122*0c0910bfSGreg Roach            'title'                      => I18N::translate('Control panel'),
123*0c0910bfSGreg Roach            'server_errors'              => $this->server_check_service->serverErrors(),
124*0c0910bfSGreg Roach            'server_warnings'            => $this->server_check_service->serverWarnings(),
125*0c0910bfSGreg Roach            'latest_version'             => $this->upgrade_service->latestVersion(),
126*0c0910bfSGreg Roach            'all_users'                  => $this->user_service->all(),
127*0c0910bfSGreg Roach            'administrators'             => $this->user_service->administrators(),
128*0c0910bfSGreg Roach            'managers'                   => $this->user_service->managers(),
129*0c0910bfSGreg Roach            'moderators'                 => $this->user_service->moderators(),
130*0c0910bfSGreg Roach            'unapproved'                 => $this->user_service->unapproved(),
131*0c0910bfSGreg Roach            'unverified'                 => $this->user_service->unverified(),
132*0c0910bfSGreg Roach            'all_trees'                  => $this->tree_service->all(),
133*0c0910bfSGreg Roach            'changes'                    => $this->totalChanges(),
134*0c0910bfSGreg Roach            'individuals'                => $this->totalIndividuals(),
135*0c0910bfSGreg Roach            'families'                   => $this->totalFamilies(),
136*0c0910bfSGreg Roach            'sources'                    => $this->totalSources(),
137*0c0910bfSGreg Roach            'media'                      => $this->totalMediaObjects(),
138*0c0910bfSGreg Roach            'repositories'               => $this->totalRepositories(),
139*0c0910bfSGreg Roach            'notes'                      => $this->totalNotes(),
140*0c0910bfSGreg Roach            'individual_list_module'     => $this->module_service->findByInterface(IndividualListModule::class)->first(),
141*0c0910bfSGreg Roach            'family_list_module'         => $this->module_service->findByInterface(FamilyListModule::class)->first(),
142*0c0910bfSGreg Roach            'media_list_module'          => $this->module_service->findByInterface(MediaListModule::class)->first(),
143*0c0910bfSGreg Roach            'note_list_module'           => $this->module_service->findByInterface(NoteListModule::class)->first(),
144*0c0910bfSGreg Roach            'repository_list_module'     => $this->module_service->findByInterface(RepositoryListModule::class)->first(),
145*0c0910bfSGreg Roach            'source_list_module'         => $this->module_service->findByInterface(SourceListModule::class)->first(),
146*0c0910bfSGreg Roach            'files_to_delete'            => $files_to_delete,
147*0c0910bfSGreg Roach            'all_modules_disabled'       => $this->module_service->all(true),
148*0c0910bfSGreg Roach            'all_modules_enabled'        => $this->module_service->all(),
149*0c0910bfSGreg Roach            'deleted_modules'            => $this->module_service->deletedModules(),
150*0c0910bfSGreg Roach            'analytics_modules_disabled' => $this->module_service->findByInterface(ModuleAnalyticsInterface::class, true),
151*0c0910bfSGreg Roach            'analytics_modules_enabled'  => $this->module_service->findByInterface(ModuleAnalyticsInterface::class),
152*0c0910bfSGreg Roach            'block_modules_disabled'     => $this->module_service->findByInterface(ModuleBlockInterface::class, true),
153*0c0910bfSGreg Roach            'block_modules_enabled'      => $this->module_service->findByInterface(ModuleBlockInterface::class),
154*0c0910bfSGreg Roach            'chart_modules_disabled'     => $this->module_service->findByInterface(ModuleChartInterface::class, true),
155*0c0910bfSGreg Roach            'chart_modules_enabled'      => $this->module_service->findByInterface(ModuleChartInterface::class),
156*0c0910bfSGreg Roach            'other_modules'              => $this->module_service->otherModules(true),
157*0c0910bfSGreg Roach            'footer_modules_disabled'    => $this->module_service->findByInterface(ModuleFooterInterface::class, true),
158*0c0910bfSGreg Roach            'footer_modules_enabled'     => $this->module_service->findByInterface(ModuleFooterInterface::class),
159*0c0910bfSGreg Roach            'history_modules_disabled'   => $this->module_service->findByInterface(ModuleHistoricEventsInterface::class, true),
160*0c0910bfSGreg Roach            'history_modules_enabled'    => $this->module_service->findByInterface(ModuleHistoricEventsInterface::class),
161*0c0910bfSGreg Roach            'language_modules_disabled'  => $this->module_service->findByInterface(ModuleLanguageInterface::class, true),
162*0c0910bfSGreg Roach            'language_modules_enabled'   => $this->module_service->findByInterface(ModuleLanguageInterface::class),
163*0c0910bfSGreg Roach            'list_modules_disabled'      => $this->module_service->findByInterface(ModuleListInterface::class, true),
164*0c0910bfSGreg Roach            'list_modules_enabled'       => $this->module_service->findByInterface(ModuleListInterface::class),
165*0c0910bfSGreg Roach            'menu_modules_disabled'      => $this->module_service->findByInterface(ModuleMenuInterface::class, true),
166*0c0910bfSGreg Roach            'menu_modules_enabled'       => $this->module_service->findByInterface(ModuleMenuInterface::class),
167*0c0910bfSGreg Roach            'report_modules_disabled'    => $this->module_service->findByInterface(ModuleReportInterface::class, true),
168*0c0910bfSGreg Roach            'report_modules_enabled'     => $this->module_service->findByInterface(ModuleReportInterface::class),
169*0c0910bfSGreg Roach            'sidebar_modules_disabled'   => $this->module_service->findByInterface(ModuleSidebarInterface::class, true),
170*0c0910bfSGreg Roach            'sidebar_modules_enabled'    => $this->module_service->findByInterface(ModuleSidebarInterface::class),
171*0c0910bfSGreg Roach            'tab_modules_disabled'       => $this->module_service->findByInterface(ModuleTabInterface::class, true),
172*0c0910bfSGreg Roach            'tab_modules_enabled'        => $this->module_service->findByInterface(ModuleTabInterface::class),
173*0c0910bfSGreg Roach            'theme_modules_disabled'     => $this->module_service->findByInterface(ModuleThemeInterface::class, true),
174*0c0910bfSGreg Roach            'theme_modules_enabled'      => $this->module_service->findByInterface(ModuleThemeInterface::class),
175*0c0910bfSGreg Roach        ]);
176*0c0910bfSGreg Roach    }
177*0c0910bfSGreg Roach
178*0c0910bfSGreg Roach    /**
179*0c0910bfSGreg Roach     * Count the number of pending changes in each tree.
180*0c0910bfSGreg Roach     *
181*0c0910bfSGreg Roach     * @return string[]
182*0c0910bfSGreg Roach     */
183*0c0910bfSGreg Roach    private function totalChanges(): array
184*0c0910bfSGreg Roach    {
185*0c0910bfSGreg Roach        return DB::table('gedcom')
186*0c0910bfSGreg Roach            ->leftJoin('change', static function (JoinClause $join): void {
187*0c0910bfSGreg Roach                $join
188*0c0910bfSGreg Roach                    ->on('change.gedcom_id', '=', 'gedcom.gedcom_id')
189*0c0910bfSGreg Roach                    ->where('change.status', '=', 'pending');
190*0c0910bfSGreg Roach            })
191*0c0910bfSGreg Roach            ->groupBy(['gedcom.gedcom_id'])
192*0c0910bfSGreg Roach            ->pluck(new Expression('COUNT(change_id)'), 'gedcom.gedcom_id')
193*0c0910bfSGreg Roach            ->all();
194*0c0910bfSGreg Roach    }
195*0c0910bfSGreg Roach
196*0c0910bfSGreg Roach    /**
197*0c0910bfSGreg Roach     * Count the number of individuals in each tree.
198*0c0910bfSGreg Roach     *
199*0c0910bfSGreg Roach     * @return Collection
200*0c0910bfSGreg Roach     */
201*0c0910bfSGreg Roach    private function totalIndividuals(): Collection
202*0c0910bfSGreg Roach    {
203*0c0910bfSGreg Roach        return DB::table('gedcom')
204*0c0910bfSGreg Roach            ->leftJoin('individuals', 'i_file', '=', 'gedcom_id')
205*0c0910bfSGreg Roach            ->groupBy(['gedcom_id'])
206*0c0910bfSGreg Roach            ->pluck(new Expression('COUNT(i_id)'), 'gedcom_id')
207*0c0910bfSGreg Roach            ->map(static function (string $count) {
208*0c0910bfSGreg Roach                return (int) $count;
209*0c0910bfSGreg Roach            });
210*0c0910bfSGreg Roach    }
211*0c0910bfSGreg Roach
212*0c0910bfSGreg Roach    /**
213*0c0910bfSGreg Roach     * Count the number of families in each tree.
214*0c0910bfSGreg Roach     *
215*0c0910bfSGreg Roach     * @return Collection
216*0c0910bfSGreg Roach     */
217*0c0910bfSGreg Roach    private function totalFamilies(): Collection
218*0c0910bfSGreg Roach    {
219*0c0910bfSGreg Roach        return DB::table('gedcom')
220*0c0910bfSGreg Roach            ->leftJoin('families', 'f_file', '=', 'gedcom_id')
221*0c0910bfSGreg Roach            ->groupBy(['gedcom_id'])
222*0c0910bfSGreg Roach            ->pluck(new Expression('COUNT(f_id)'), 'gedcom_id')
223*0c0910bfSGreg Roach            ->map(static function (string $count) {
224*0c0910bfSGreg Roach                return (int) $count;
225*0c0910bfSGreg Roach            });
226*0c0910bfSGreg Roach    }
227*0c0910bfSGreg Roach
228*0c0910bfSGreg Roach    /**
229*0c0910bfSGreg Roach     * Count the number of sources in each tree.
230*0c0910bfSGreg Roach     *
231*0c0910bfSGreg Roach     * @return Collection
232*0c0910bfSGreg Roach     */
233*0c0910bfSGreg Roach    private function totalSources(): Collection
234*0c0910bfSGreg Roach    {
235*0c0910bfSGreg Roach        return DB::table('gedcom')
236*0c0910bfSGreg Roach            ->leftJoin('sources', 's_file', '=', 'gedcom_id')
237*0c0910bfSGreg Roach            ->groupBy(['gedcom_id'])
238*0c0910bfSGreg Roach            ->pluck(new Expression('COUNT(s_id)'), 'gedcom_id')
239*0c0910bfSGreg Roach            ->map(static function (string $count) {
240*0c0910bfSGreg Roach                return (int) $count;
241*0c0910bfSGreg Roach            });
242*0c0910bfSGreg Roach    }
243*0c0910bfSGreg Roach
244*0c0910bfSGreg Roach    /**
245*0c0910bfSGreg Roach     * Count the number of media objects in each tree.
246*0c0910bfSGreg Roach     *
247*0c0910bfSGreg Roach     * @return Collection
248*0c0910bfSGreg Roach     */
249*0c0910bfSGreg Roach    private function totalMediaObjects(): Collection
250*0c0910bfSGreg Roach    {
251*0c0910bfSGreg Roach        return DB::table('gedcom')
252*0c0910bfSGreg Roach            ->leftJoin('media', 'm_file', '=', 'gedcom_id')
253*0c0910bfSGreg Roach            ->groupBy(['gedcom_id'])
254*0c0910bfSGreg Roach            ->pluck(new Expression('COUNT(m_id)'), 'gedcom_id')
255*0c0910bfSGreg Roach            ->map(static function (string $count) {
256*0c0910bfSGreg Roach                return (int) $count;
257*0c0910bfSGreg Roach            });
258*0c0910bfSGreg Roach    }
259*0c0910bfSGreg Roach
260*0c0910bfSGreg Roach    /**
261*0c0910bfSGreg Roach     * Count the number of repositorie in each tree.
262*0c0910bfSGreg Roach     *
263*0c0910bfSGreg Roach     * @return Collection
264*0c0910bfSGreg Roach     */
265*0c0910bfSGreg Roach    private function totalRepositories(): Collection
266*0c0910bfSGreg Roach    {
267*0c0910bfSGreg Roach        return DB::table('gedcom')
268*0c0910bfSGreg Roach            ->leftJoin('other', static function (JoinClause $join): void {
269*0c0910bfSGreg Roach                $join
270*0c0910bfSGreg Roach                    ->on('o_file', '=', 'gedcom_id')
271*0c0910bfSGreg Roach                    ->where('o_type', '=', 'REPO');
272*0c0910bfSGreg Roach            })
273*0c0910bfSGreg Roach            ->groupBy(['gedcom_id'])
274*0c0910bfSGreg Roach            ->pluck(new Expression('COUNT(o_id)'), 'gedcom_id')
275*0c0910bfSGreg Roach            ->map(static function (string $count) {
276*0c0910bfSGreg Roach                return (int) $count;
277*0c0910bfSGreg Roach            });
278*0c0910bfSGreg Roach    }
279*0c0910bfSGreg Roach
280*0c0910bfSGreg Roach    /**
281*0c0910bfSGreg Roach     * Count the number of notes in each tree.
282*0c0910bfSGreg Roach     *
283*0c0910bfSGreg Roach     * @return Collection
284*0c0910bfSGreg Roach     */
285*0c0910bfSGreg Roach    private function totalNotes(): Collection
286*0c0910bfSGreg Roach    {
287*0c0910bfSGreg Roach        return DB::table('gedcom')
288*0c0910bfSGreg Roach            ->leftJoin('other', static function (JoinClause $join): void {
289*0c0910bfSGreg Roach                $join
290*0c0910bfSGreg Roach                    ->on('o_file', '=', 'gedcom_id')
291*0c0910bfSGreg Roach                    ->where('o_type', '=', 'NOTE');
292*0c0910bfSGreg Roach            })
293*0c0910bfSGreg Roach            ->groupBy(['gedcom_id'])
294*0c0910bfSGreg Roach            ->pluck(new Expression('COUNT(o_id)'), 'gedcom_id')
295*0c0910bfSGreg Roach            ->map(static function (string $count) {
296*0c0910bfSGreg Roach                return (int) $count;
297*0c0910bfSGreg Roach            });
298*0c0910bfSGreg Roach    }
299*0c0910bfSGreg Roach}
300