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/SpecialChars', 450 'assets/js-1.7.7', 451 'assets/js-1.7.9', 452 'autocomplete.php', 453 'block_edit.php', 454 'branches.php', 455 'calendar.php', 456 'compact.php', 457 'data/html_purifier_cache', 458 'descendancy.php', 459 'editnews.php', 460 'edituser.php', 461 'edit_changes.php', 462 'edit_interface.php', 463 'expand_view.php', 464 'familybook.php', 465 'famlist.php', 466 'fanchart.php', 467 'find.php', 468 'help_text.php', 469 'hourglass.php', 470 'hourglass_ajax.php', 471 'import.php', 472 'includes', 473 'index_edit.php', 474 'indilist.php', 475 'inverselink.php', 476 'lifespan.php', 477 'login.php', 478 'logout.php', 479 'mediafirewall.php', 480 'medialist.php', 481 'message.php', 482 'module.php', 483 'notelist.php', 484 'packages', 485 'pedigree.php', 486 'relationship.php', 487 'repolist.php', 488 'reportengine.php', 489 'search.php', 490 'search_advanced.php', 491 'site-offline.php', 492 'site-unavailable.php', 493 'sourcelist.php', 494 'statistics.php', 495 'statisticsplot.php', 496 'themes/_administration', 497 'themes/_custom', 498 'themes/clouds/css-1.7.8', 499 'themes/clouds/jquery-ui-1.11.2', 500 'themes/colors/css-1.7.8', 501 'themes/colors/jquery-ui-1.11.2', 502 'themes/fab/css-1.7.8', 503 'themes/fab/jquery-ui-1.11.2', 504 'themes/minimal/css-1.7.8', 505 'themes/minimal/jquery-ui-1.11.2', 506 'themes/webtrees/css-1.7.8', 507 'themes/webtrees/jquery-ui-1.11.2', 508 'themes/xenea/css-1.7.8', 509 'themes/xenea/jquery-ui-1.11.2', 510 'timeline.php', 511 ]; 512 513 /** 514 * Delete files and folders that belonged to an earlier version of webtrees. 515 * Return a list of those that we could not delete. 516 * 517 * @param Filesystem $filesystem 518 * 519 * @return array 520 */ 521 public function deleteOldWebtreesFiles(Filesystem $filesystem): array 522 { 523 $paths_to_delete = []; 524 525 foreach (self::OLD_PATHS as $path) { 526 if (!$this->deleteFileOrFolder($filesystem, $path)) { 527 $paths_to_delete[] = $path; 528 } 529 } 530 531 return $paths_to_delete; 532 } 533 534 /** 535 * Delete old cache files. 536 * 537 * @param Filesystem $filesystem 538 * @param string $path_to_cache 539 * @param int $max_age_in_seconds 540 */ 541 public function deleteOldCacheFiles(Filesystem $filesystem, string $path_to_cache, int $max_age_in_seconds) 542 { 543 $list = $filesystem->listContents($path_to_cache, true); 544 545 foreach ($list as $metadata) { 546 if ($metadata['timestamp'] ?? WT_TIMESTAMP < WT_TIMESTAMP - $max_age_in_seconds) { 547 $this->deleteFileOrFolder($filesystem, $metadata['path']); 548 } 549 } 550 } 551 552 /** 553 * @param int $max_age_in_seconds 554 */ 555 public function deleteOldLogs(int $max_age_in_seconds) 556 { 557 if (Database::isConnected()) { 558 Database::prepare( 559 "DELETE FROM `##log` WHERE log_type IN ('error', 'media') AND log_time < FROM_UNIXTIME(:timestamp)" 560 )->execute([ 561 'timestamp' => WT_TIMESTAMP - $max_age_in_seconds 562 ]); 563 } 564 } 565 566 /** 567 * @param int $max_age_in_seconds 568 */ 569 public function deleteOldSessions(int $max_age_in_seconds) 570 { 571 if (Database::isConnected()) { 572 Database::prepare( 573 "DELETE FROM `##session` WHERE session_time < FROM_UNIXTIME(:timestamp)" 574 )->execute([ 575 'timestamp' => WT_TIMESTAMP - $max_age_in_seconds 576 ]); 577 } 578 } 579 580 /** 581 * Delete a file or folder, if we can. 582 * 583 * @param Filesystem $filesystem 584 * @param string $path 585 * 586 * @return bool 587 */ 588 private function deleteFileOrFolder(Filesystem $filesystem, string $path): bool 589 { 590 if ($filesystem->has($path)) { 591 try { 592 $metadata = $filesystem->getMetadata($path); 593 594 if ($metadata['type'] === 'dir') { 595 $filesystem->deleteDir($path); 596 } 597 598 if ($metadata['type'] === 'file') { 599 $filesystem->delete($path); 600 } 601 } catch (Exception $ex) { 602 return false; 603 } 604 } 605 606 return true; 607 } 608} 609