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