xref: /webtrees/app/Services/HousekeepingService.php (revision a7a24840b43d2ed5c53b60c55f1f09e1cc2f01f9)
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 */
16declare(strict_types=1);
17
18namespace Fisharebest\Webtrees\Services;
19
20use Exception;
21use Illuminate\Database\Capsule\Manager as DB;
22use League\Flysystem\Filesystem;
23
24/**
25 * Clean up old data, files and folders.
26 */
27class HousekeepingService
28{
29    // This is a list of old files and directories, from earlier versions of webtrees.
30    // git diff 1.7.9..master --name-status | grep ^D
31    private const OLD_PATHS = [
32        // Removed in 1.0.2
33        'language/en.mo',
34        // Removed in 1.0.3
35        'themechange.php',
36        // Removed in 1.1.0
37        'addremotelink.php',
38        'addsearchlink.php',
39        'client.php',
40        'dir_editor.php',
41        'editconfig_gedcom.php',
42        'editgedcoms.php',
43        'edit_merge.php',
44        'edit_news.php',
45        'genservice.php',
46        'logs.php',
47        'manageservers.php',
48        'media.php',
49        'module_admin.php',
50        //WT_ROOT.'modules', // Do not delete - users may have stored custom modules/data here
51        'opensearch.php',
52        'PEAR.php',
53        'pgv_to_wt.php',
54        'places',
55        //WT_ROOT.'robots.txt', // Do not delete this - it may contain user data
56        'serviceClientTest.php',
57        'siteconfig.php',
58        'SOAP',
59        'themes/clouds/mozilla.css',
60        'themes/clouds/netscape.css',
61        'themes/colors/mozilla.css',
62        'themes/colors/netscape.css',
63        'themes/fab/mozilla.css',
64        'themes/fab/netscape.css',
65        'themes/minimal/mozilla.css',
66        'themes/minimal/netscape.css',
67        'themes/webtrees/mozilla.css',
68        'themes/webtrees/netscape.css',
69        'themes/webtrees/style_rtl.css',
70        'themes/xenea/mozilla.css',
71        'themes/xenea/netscape.css',
72        'uploadmedia.php',
73        'useradmin.php',
74        'webservice',
75        'wtinfo.php',
76        // Removed in 1.1.2
77        'treenav.php',
78        // Removed in 1.2.0
79        'themes/clouds/jquery',
80        'themes/colors/jquery',
81        'themes/fab/jquery',
82        'themes/minimal/jquery',
83        'themes/webtrees/jquery',
84        'themes/xenea/jquery',
85        // Removed in 1.2.2
86        'themes/clouds/chrome.css',
87        'themes/clouds/opera.css',
88        'themes/clouds/print.css',
89        'themes/clouds/style_rtl.css',
90        'themes/colors/chrome.css',
91        'themes/colors/opera.css',
92        'themes/colors/print.css',
93        'themes/colors/style_rtl.css',
94        'themes/fab/chrome.css',
95        'themes/fab/opera.css',
96        'themes/minimal/chrome.css',
97        'themes/minimal/opera.css',
98        'themes/minimal/print.css',
99        'themes/minimal/style_rtl.css',
100        'themes/xenea/chrome.css',
101        'themes/xenea/opera.css',
102        'themes/xenea/print.css',
103        'themes/xenea/style_rtl.css',
104        // Removed in 1.2.3
105        //WT_ROOT.'modules_v2', // Do not delete - users may have stored custom modules/data here
106        // Removed in 1.2.4
107        'modules_v3/gedcom_favorites/help_text.php',
108        'modules_v3/GEDFact_assistant/_MEDIA/media_3_find.php',
109        'modules_v3/GEDFact_assistant/_MEDIA/media_3_search_add.php',
110        'modules_v3/GEDFact_assistant/_MEDIA/media_5_input.js',
111        'modules_v3/GEDFact_assistant/_MEDIA/media_5_input.php',
112        'modules_v3/GEDFact_assistant/_MEDIA/media_7_parse_addLinksTbl.php',
113        'modules_v3/GEDFact_assistant/_MEDIA/media_query_1a.php',
114        'modules_v3/GEDFact_assistant/_MEDIA/media_query_2a.php',
115        'modules_v3/GEDFact_assistant/_MEDIA/media_query_3a.php',
116        'modules_v3/lightbox/css/album_page_RTL2.css',
117        'modules_v3/lightbox/css/album_page_RTL.css',
118        'modules_v3/lightbox/css/album_page_RTL_ff.css',
119        'modules_v3/lightbox/css/clearbox_music.css',
120        'modules_v3/lightbox/css/clearbox_music_RTL.css',
121        'modules_v3/user_favorites/db_schema',
122        'modules_v3/user_favorites/help_text.php',
123        'search_engine.php',
124        'themes/clouds/modules.css',
125        'themes/colors/modules.css',
126        'themes/fab/modules.css',
127        'themes/minimal/modules.css',
128        'themes/webtrees/modules.css',
129        'themes/xenea/modules.css',
130        // Removed in 1.2.5
131        'modules_v3/clippings/index.php',
132        'modules_v3/googlemap/css/googlemap_style.css',
133        'modules_v3/googlemap/css/wt_v3_places_edit.css',
134        'modules_v3/googlemap/index.php',
135        'modules_v3/lightbox/index.php',
136        'modules_v3/recent_changes/help_text.php',
137        'modules_v3/todays_events/help_text.php',
138        'sidebar.php',
139        // Removed in 1.2.6
140        'modules_v3/sitemap/admin_index.php',
141        'modules_v3/sitemap/help_text.php',
142        'modules_v3/tree/css/styles',
143        'modules_v3/tree/css/treebottom.gif',
144        'modules_v3/tree/css/treebottomleft.gif',
145        'modules_v3/tree/css/treebottomright.gif',
146        'modules_v3/tree/css/tree.jpg',
147        'modules_v3/tree/css/treeleft.gif',
148        'modules_v3/tree/css/treeright.gif',
149        'modules_v3/tree/css/treetop.gif',
150        'modules_v3/tree/css/treetopleft.gif',
151        'modules_v3/tree/css/treetopright.gif',
152        'modules_v3/tree/css/treeview_print.css',
153        'modules_v3/tree/help_text.php',
154        'modules_v3/tree/images/print.png',
155        // Removed in 1.2.7
156        'login_register.php',
157        'modules_v3/top10_givnnames/help_text.php',
158        'modules_v3/top10_surnames/help_text.php',
159        // Removed in 1.3.0
160        'admin_site_ipaddress.php',
161        'downloadgedcom.php',
162        'export_gedcom.php',
163        'gedcheck.php',
164        'images',
165        'modules_v3/googlemap/admin_editconfig.php',
166        'modules_v3/googlemap/admin_placecheck.php',
167        'modules_v3/googlemap/flags.php',
168        'modules_v3/googlemap/images/pedigree_map.gif',
169        'modules_v3/googlemap/pedigree_map.php',
170        'modules_v3/lightbox/admin_config.php',
171        'modules_v3/lightbox/album.php',
172        'modules_v3/tree/css/vline.jpg',
173        // Removed in 1.3.1
174        'imageflush.php',
175        'modules_v3/googlemap/wt_v3_pedigree_map.js.php',
176        'modules_v3/lightbox/js/tip_balloon_RTL.js',
177        // Removed in 1.3.2
178        'modules_v3/address_report',
179        'modules_v3/lightbox/functions/lb_horiz_sort.php',
180        'modules_v3/random_media/help_text.php',
181        // Removed in 1.4.0
182        'imageview.php',
183        'media/MediaInfo.txt',
184        'media/thumbs/ThumbsInfo.txt',
185        'modules_v3/GEDFact_assistant/css/media_0_inverselink.css',
186        'modules_v3/lightbox/help_text.php',
187        'modules_v3/lightbox/images/blank.gif',
188        'modules_v3/lightbox/images/close_1.gif',
189        'modules_v3/lightbox/images/image_add.gif',
190        'modules_v3/lightbox/images/image_copy.gif',
191        'modules_v3/lightbox/images/image_delete.gif',
192        'modules_v3/lightbox/images/image_edit.gif',
193        'modules_v3/lightbox/images/image_link.gif',
194        'modules_v3/lightbox/images/images.gif',
195        'modules_v3/lightbox/images/image_view.gif',
196        'modules_v3/lightbox/images/loading.gif',
197        'modules_v3/lightbox/images/next.gif',
198        'modules_v3/lightbox/images/nextlabel.gif',
199        'modules_v3/lightbox/images/norm_2.gif',
200        'modules_v3/lightbox/images/overlay.png',
201        'modules_v3/lightbox/images/prev.gif',
202        'modules_v3/lightbox/images/prevlabel.gif',
203        'modules_v3/lightbox/images/private.gif',
204        'modules_v3/lightbox/images/slideshow.jpg',
205        'modules_v3/lightbox/images/transp80px.gif',
206        'modules_v3/lightbox/images/zoom_1.gif',
207        'modules_v3/lightbox/js',
208        'modules_v3/lightbox/music',
209        'modules_v3/lightbox/pic',
210        'themes/webtrees/chrome.css',
211        // Removed in 1.4.1
212        'modules_v3/lightbox/images/image_edit.png',
213        'modules_v3/lightbox/images/image_view.png',
214        // Removed in 1.4.2
215        'modules_v3/lightbox/images/image_view.png',
216        'modules_v3/top10_pageviews/help_text.php',
217        'themes/clouds/jquery-ui-1.10.0',
218        'themes/colors/jquery-ui-1.10.0',
219        'themes/fab/jquery-ui-1.10.0',
220        'themes/minimal/jquery-ui-1.10.0',
221        'themes/webtrees/jquery-ui-1.10.0',
222        'themes/xenea/jquery-ui-1.10.0',
223        // Removed in 1.5.0
224        'modules_v3/GEDFact_assistant/_CENS/census_note_decode.php',
225        'modules_v3/GEDFact_assistant/_CENS/census_asst_date.php',
226        'modules_v3/googlemap/wt_v3_googlemap.js.php',
227        'modules_v3/lightbox/functions/lightbox_print_media.php',
228        'modules_v3/upcoming_events/help_text.php',
229        'modules_v3/stories/help_text.php',
230        'modules_v3/user_messages/help_text.php',
231        'themes/clouds/favicon.png',
232        'themes/clouds/images',
233        'themes/clouds/msie.css',
234        'themes/clouds/style.css',
235        'themes/colors/css',
236        'themes/colors/favicon.png',
237        'themes/colors/images',
238        'themes/colors/ipad.css',
239        'themes/colors/msie.css',
240        'themes/fab/favicon.png',
241        'themes/fab/images',
242        'themes/fab/msie.css',
243        'themes/fab/style.css',
244        'themes/minimal/favicon.png',
245        'themes/minimal/images',
246        'themes/minimal/msie.css',
247        'themes/minimal/style.css',
248        'themes/webtrees/favicon.png',
249        'themes/webtrees/images',
250        'themes/webtrees/msie.css',
251        'themes/webtrees/style.css',
252        'themes/xenea/favicon.png',
253        'themes/xenea/images',
254        'themes/xenea/msie.css',
255        'themes/xenea/style.css',
256        // Removed in 1.5.1
257        'themes/clouds/css-1.5.0',
258        'themes/colors/css-1.5.0',
259        'themes/fab/css-1.5.0',
260        'themes/minimal/css-1.5.0',
261        'themes/webtrees/css-1.5.0',
262        'themes/xenea/css-1.5.0',
263        // Removed in 1.5.2
264        'themes/clouds/css-1.5.1',
265        'themes/colors/css-1.5.1',
266        'themes/fab/css-1.5.1',
267        'themes/minimal/css-1.5.1',
268        'themes/webtrees/css-1.5.1',
269        'themes/xenea/css-1.5.1',
270        // Removed in 1.5.3
271        'modules_v3/GEDFact_assistant/_CENS/census_asst_help.php',
272        'modules_v3/googlemap/admin_places.php',
273        'modules_v3/googlemap/defaultconfig.php',
274        'modules_v3/googlemap/googlemap.php',
275        'modules_v3/googlemap/placehierarchy.php',
276        'modules_v3/googlemap/places_edit.php',
277        'modules_v3/googlemap/util.js',
278        'modules_v3/googlemap/wt_v3_places_edit.js.php',
279        'modules_v3/googlemap/wt_v3_places_edit_overlays.js.php',
280        'modules_v3/googlemap/wt_v3_street_view.php',
281        'readme.html',
282        'themes/clouds/css-1.5.2',
283        'themes/colors/css-1.5.2',
284        'themes/fab/css-1.5.2',
285        'themes/minimal/css-1.5.2',
286        'themes/webtrees/css-1.5.2',
287        'themes/xenea/css-1.5.2',
288        // Removed in 1.6.0
289        'downloadbackup.php',
290        'modules_v3/ckeditor/ckeditor-4.3.2-custom',
291        'site-php-version.php',
292        'themes/clouds/css-1.5.3',
293        'themes/colors/css-1.5.3',
294        'themes/fab/css-1.5.3',
295        'themes/minimal/css-1.5.3',
296        'themes/webtrees/css-1.5.3',
297        'themes/xenea/css-1.5.3',
298        // Removed in 1.6.2
299        'themes/clouds/jquery-ui-1.10.3',
300        'themes/colors/css-1.6.0',
301        'themes/colors/jquery-ui-1.10.3',
302        'themes/fab/css-1.6.0',
303        'themes/fab/jquery-ui-1.10.3',
304        'themes/minimal/css-1.6.0',
305        'themes/minimal/jquery-ui-1.10.3',
306        'themes/webtrees/css-1.6.0',
307        'themes/webtrees/jquery-ui-1.10.3',
308        'themes/xenea/css-1.6.0',
309        'themes/xenea/jquery-ui-1.10.3',
310        // Removed in 1.7.0
311        'admin_site_other.php',
312        'js',
313        'language/en_GB.mo',
314        // Replaced with en-GB.mo
315        'language/en_US.mo',
316        // Replaced with en-US.mo
317        'language/pt_BR.mo',
318        // Replaced with pt-BR.mo
319        'language/zh_CN.mo',
320        // Replaced with zh-Hans.mo
321        'language/extra',
322        'library',
323        'modules_v3/batch_update/admin_batch_update.php',
324        'modules_v3/batch_update/plugins',
325        'modules_v3/charts/help_text.php',
326        'modules_v3/ckeditor/ckeditor-4.4.1-custom',
327        'modules_v3/clippings/clippings_ctrl.php',
328        'modules_v3/clippings/help_text.php',
329        'modules_v3/faq/help_text.php',
330        'modules_v3/gedcom_favorites/db_schema',
331        'modules_v3/gedcom_news/db_schema',
332        'modules_v3/googlemap/db_schema',
333        'modules_v3/googlemap/help_text.php',
334        'modules_v3/html/help_text.php',
335        'modules_v3/logged_in/help_text.php',
336        'modules_v3/review_changes/help_text.php',
337        'modules_v3/todo/help_text.php',
338        'modules_v3/tree/class_treeview.php',
339        'modules_v3/user_blog/db_schema',
340        'modules_v3/yahrzeit/help_text.php',
341        'save.php',
342        'themes/clouds/css-1.6.2',
343        'themes/clouds/templates',
344        'themes/clouds/header.php',
345        'themes/clouds/footer.php',
346        'themes/colors/css-1.6.2',
347        'themes/colors/templates',
348        'themes/colors/header.php',
349        'themes/colors/footer.php',
350        'themes/fab/css-1.6.2',
351        'themes/fab/templates',
352        'themes/fab/header.php',
353        'themes/fab/footer.php',
354        'themes/minimal/css-1.6.2',
355        'themes/minimal/templates',
356        'themes/minimal/header.php',
357        'themes/minimal/footer.php',
358        'themes/webtrees/css-1.6.2',
359        'themes/webtrees/templates',
360        'themes/webtrees/header.php',
361        'themes/webtrees/footer.php',
362        'themes/xenea/css-1.6.2',
363        'themes/xenea/templates',
364        'themes/xenea/header.php',
365        'themes/xenea/footer.php',
366        // Removed in 1.7.2
367        'assets/js-1.7.0',
368        // Removed in 1.7.3
369        'modules_v3/GEDFact_assistant/census/date.js',
370        'modules_v3/GEDFact_assistant/census/dynamicoptionlist.js',
371        // Removed in 1.7.4
372        'assets/js-1.7.2',
373        'themes/clouds/css-1.7.0',
374        'themes/colors/css-1.7.0',
375        'themes/fab/css-1.7.0',
376        'themes/minimal/css-1.7.0',
377        'themes/webtrees/css-1.7.0',
378        'themes/xenea/css-1.7.0',
379        // Removed in 1.7.5
380        'themes/clouds/css-1.7.4',
381        'themes/colors/css-1.7.4',
382        'themes/fab/css-1.7.4',
383        'themes/minimal/css-1.7.4',
384        'themes/webtrees/css-1.7.4',
385        'themes/xenea/css-1.7.4',
386        // Removed in 1.7.7
387        'assets/js-1.7.4',
388        'modules_v3/googlemap/images/css_sprite_facts.png',
389        'modules_v3/googlemap/images/flag_shadow.png',
390        'modules_v3/googlemap/images/shadow-left-large.png',
391        'modules_v3/googlemap/images/shadow-left-small.png',
392        'modules_v3/googlemap/images/shadow-right-large.png',
393        'modules_v3/googlemap/images/shadow-right-small.png',
394        'modules_v3/googlemap/images/shadow50.png',
395        'modules_v3/googlemap/images/transparent-left-large.png',
396        'modules_v3/googlemap/images/transparent-left-small.png',
397        'modules_v3/googlemap/images/transparent-right-large.png',
398        'modules_v3/googlemap/images/transparent-right-small.png',
399        // Removed in 1.7.8
400        'themes/clouds/css-1.7.5',
401        'themes/colors/css-1.7.5',
402        'themes/fab/css-1.7.5',
403        'themes/minimal/css-1.7.5',
404        'themes/webtrees/css-1.7.5',
405        'themes/xenea/css-1.7.5',
406        // Removed in 2.0.0
407        'action.php',
408        'addmedia.php',
409        'addmin.php',
410        'admin_media.php',
411        'admin_media_upload.php',
412        'admin_module_blocks.php',
413        'admin_module_charts.php',
414        'admin_module_menus.php',
415        'admin_module_reports.php',
416        'admin_module_sidebar.php',
417        'admin_module_tabs.php',
418        'admin_modules.php',
419        'admin_pgv_to_wt.php',
420        'admin_site_access.php',
421        'admin_site_change.php',
422        'admin_site_clean.php',
423        'admin_site_config.php',
424        'admin_site_info.php',
425        'admin_site_logs.php',
426        'admin_site_merge.php',
427        'admin_site_readme.php',
428        'admin_site_upgrade.php',
429        'admin_trees_check.php',
430        'admin_trees_config.php',
431        'admin_trees_download.php',
432        'admin_trees_duplicates.php',
433        'admin_trees_export.php',
434        'admin_trees_manage.php',
435        'admin_trees_merge.php',
436        'admin_trees_places.php',
437        'admin_trees_renumber.php',
438        'admin_trees_unconnected.php',
439        'admin_users.php',
440        'admin_users_bulk.php',
441        'ancestry.php',
442        'app/Controller',
443        'app/HitCounter.php',
444        'app/Module/ClippingsCart/ClippingsCartController.php',
445        'app/Module/FamiliesSidebarModule.php',
446        'app/Module/FamilyTreeFavorites',
447        'app/Module/GoogleMaps',
448        'app/Module/IndividualSidebarModule.php',
449        'app/Module/PageMenuModule.php',
450        'app/Query',
451        'app/SpecialChars',
452        'assets/js-1.7.7',
453        'assets/js-1.7.9',
454        'autocomplete.php',
455        'block_edit.php',
456        'branches.php',
457        'calendar.php',
458        'compact.php',
459        'data/html_purifier_cache',
460        'descendancy.php',
461        'editnews.php',
462        'edituser.php',
463        'edit_changes.php',
464        'edit_interface.php',
465        'expand_view.php',
466        'familybook.php',
467        'famlist.php',
468        'fanchart.php',
469        'find.php',
470        'help_text.php',
471        'hourglass.php',
472        'hourglass_ajax.php',
473        'import.php',
474        'includes',
475        'index_edit.php',
476        'indilist.php',
477        'inverselink.php',
478        'lifespan.php',
479        'login.php',
480        'logout.php',
481        'mediafirewall.php',
482        'medialist.php',
483        'message.php',
484        'module.php',
485        'notelist.php',
486        'packages',
487        'pedigree.php',
488        'relationship.php',
489        'repolist.php',
490        'reportengine.php',
491        'search.php',
492        'search_advanced.php',
493        'site-offline.php',
494        'site-unavailable.php',
495        'sourcelist.php',
496        'statistics.php',
497        'statisticsplot.php',
498        'themes/_administration',
499        'themes/_custom',
500        'themes/clouds/css-1.7.8',
501        'themes/clouds/jquery-ui-1.11.2',
502        'themes/colors/css-1.7.8',
503        'themes/colors/jquery-ui-1.11.2',
504        'themes/fab/css-1.7.8',
505        'themes/fab/jquery-ui-1.11.2',
506        'themes/minimal/css-1.7.8',
507        'themes/minimal/jquery-ui-1.11.2',
508        'themes/webtrees/css-1.7.8',
509        'themes/webtrees/jquery-ui-1.11.2',
510        'themes/xenea/css-1.7.8',
511        'themes/xenea/jquery-ui-1.11.2',
512        'timeline.php',
513    ];
514
515    /**
516     * Delete files and folders that belonged to an earlier version of webtrees.
517     * Return a list of those that we could not delete.
518     *
519     * @param Filesystem $filesystem
520     *
521     * @return array
522     */
523    public function deleteOldWebtreesFiles(Filesystem $filesystem): array
524    {
525        $paths_to_delete = [];
526
527        foreach (self::OLD_PATHS as $path) {
528            if (!$this->deleteFileOrFolder($filesystem, $path)) {
529                $paths_to_delete[] = $path;
530            }
531        }
532
533        return $paths_to_delete;
534    }
535
536    /**
537     * Delete old cache files.
538     *
539     * @param Filesystem $filesystem
540     * @param string     $path_to_cache
541     * @param int        $max_age_in_seconds
542     *
543     * @return void
544     */
545    public function deleteOldCacheFiles(Filesystem $filesystem, string $path_to_cache, int $max_age_in_seconds)
546    {
547        $list = $filesystem->listContents($path_to_cache, true);
548
549        foreach ($list as $metadata) {
550            if ($metadata['timestamp'] ?? WT_TIMESTAMP < WT_TIMESTAMP - $max_age_in_seconds) {
551                $this->deleteFileOrFolder($filesystem, $metadata['path']);
552            }
553        }
554    }
555
556    /**
557     * @param int $max_age_in_seconds
558     *
559     * @return void
560     */
561    public function deleteOldLogs(int $max_age_in_seconds)
562    {
563        DB::table('log')
564            ->whereIn('log_type', ['error', 'media'])
565            ->whereRaw('log_time < FROM_UNIXTIME(?)', [WT_TIMESTAMP - $max_age_in_seconds])
566            ->delete();
567    }
568
569    /**
570     * @param int $max_age_in_seconds
571     *
572     * @return void
573     */
574    public function deleteOldSessions(int $max_age_in_seconds)
575    {
576        DB::table('session')
577            ->whereRaw('session_time < FROM_UNIXTIME(?)', [WT_TIMESTAMP - $max_age_in_seconds])
578            ->delete();
579    }
580
581    /**
582     * Delete a file or folder, if we can.
583     *
584     * @param Filesystem $filesystem
585     * @param string     $path
586     *
587     * @return bool
588     */
589    private function deleteFileOrFolder(Filesystem $filesystem, string $path): bool
590    {
591        if ($filesystem->has($path)) {
592            try {
593                $metadata = $filesystem->getMetadata($path);
594
595                if ($metadata['type'] === 'dir') {
596                    $filesystem->deleteDir($path);
597                }
598
599                if ($metadata['type'] === 'file') {
600                    $filesystem->delete($path);
601                }
602            } catch (Exception $ex) {
603                return false;
604            }
605        }
606
607        return true;
608    }
609}
610