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