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 Fisharebest\Webtrees\Database; 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 Database::prepare( 564 "DELETE FROM `##log` WHERE log_type IN ('error', 'media') AND log_time < FROM_UNIXTIME(:timestamp)" 565 )->execute([ 566 'timestamp' => WT_TIMESTAMP - $max_age_in_seconds 567 ]); 568 } 569 570 /** 571 * @param int $max_age_in_seconds 572 * 573 * @return void 574 */ 575 public function deleteOldSessions(int $max_age_in_seconds) 576 { 577 Database::prepare( 578 "DELETE FROM `##session` WHERE session_time < FROM_UNIXTIME(:timestamp)" 579 )->execute([ 580 'timestamp' => WT_TIMESTAMP - $max_age_in_seconds 581 ]); 582 } 583 584 /** 585 * Delete a file or folder, if we can. 586 * 587 * @param Filesystem $filesystem 588 * @param string $path 589 * 590 * @return bool 591 */ 592 private function deleteFileOrFolder(Filesystem $filesystem, string $path): bool 593 { 594 if ($filesystem->has($path)) { 595 try { 596 $metadata = $filesystem->getMetadata($path); 597 598 if ($metadata['type'] === 'dir') { 599 $filesystem->deleteDir($path); 600 } 601 602 if ($metadata['type'] === 'file') { 603 $filesystem->delete($path); 604 } 605 } catch (Exception $ex) { 606 return false; 607 } 608 } 609 610 return true; 611 } 612} 613