1a3dc3edaSGreg Roach<?php 23976b470SGreg Roach 3a3dc3edaSGreg Roach/** 4a3dc3edaSGreg Roach * webtrees: online genealogy 5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team 6a3dc3edaSGreg Roach * This program is free software: you can redistribute it and/or modify 7a3dc3edaSGreg Roach * it under the terms of the GNU General Public License as published by 8a3dc3edaSGreg Roach * the Free Software Foundation, either version 3 of the License, or 9a3dc3edaSGreg Roach * (at your option) any later version. 10a3dc3edaSGreg Roach * This program is distributed in the hope that it will be useful, 11a3dc3edaSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 12a3dc3edaSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13a3dc3edaSGreg Roach * GNU General Public License for more details. 14a3dc3edaSGreg Roach * You should have received a copy of the GNU General Public License 1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 16a3dc3edaSGreg Roach */ 17fcfa147eSGreg Roach 18e7f56f2aSGreg Roachdeclare(strict_types=1); 19e7f56f2aSGreg Roach 20a3dc3edaSGreg Roachnamespace Fisharebest\Webtrees\Services; 21a3dc3edaSGreg Roach 22*6f4ec3caSGreg Roachuse Fisharebest\Webtrees\DB; 23f32d77e6SGreg Roachuse League\Flysystem\FilesystemException; 24f7cf8a15SGreg Roachuse League\Flysystem\FilesystemOperator; 25782714c2SGreg Roachuse League\Flysystem\FilesystemReader; 26f32d77e6SGreg Roachuse League\Flysystem\UnableToDeleteDirectory; 27f32d77e6SGreg Roachuse League\Flysystem\UnableToDeleteFile; 28a3dc3edaSGreg Roach 293943950dSGreg Roachuse function date; 30d97083feSGreg Roachuse function time; 31d97083feSGreg Roach 32a3dc3edaSGreg Roach/** 33a3dc3edaSGreg Roach * Clean up old data, files and folders. 34a3dc3edaSGreg Roach */ 35a3dc3edaSGreg Roachclass HousekeepingService 36a3dc3edaSGreg Roach{ 37a3dc3edaSGreg Roach // This is a list of old files and directories, from earlier versions of webtrees. 38a3dc3edaSGreg Roach // git diff 1.7.9..master --name-status | grep ^D 3916d6367aSGreg Roach private const OLD_PATHS = [ 40a3dc3edaSGreg Roach // Removed in 1.0.3 41a3dc3edaSGreg Roach 'themechange.php', 42a3dc3edaSGreg Roach // Removed in 1.1.0 43a3dc3edaSGreg Roach 'addremotelink.php', 44a3dc3edaSGreg Roach 'addsearchlink.php', 45a3dc3edaSGreg Roach 'client.php', 46a3dc3edaSGreg Roach 'dir_editor.php', 47a3dc3edaSGreg Roach 'editconfig_gedcom.php', 48a3dc3edaSGreg Roach 'editgedcoms.php', 49a3dc3edaSGreg Roach 'edit_merge.php', 50a3dc3edaSGreg Roach 'edit_news.php', 51a3dc3edaSGreg Roach 'genservice.php', 52a3dc3edaSGreg Roach 'logs.php', 53a3dc3edaSGreg Roach 'manageservers.php', 54a3dc3edaSGreg Roach 'media.php', 55a3dc3edaSGreg Roach 'module_admin.php', 56f397d0fdSGreg Roach //'modules', // Do not delete - users may have stored custom modules/data here 57a3dc3edaSGreg Roach 'opensearch.php', 58a3dc3edaSGreg Roach 'PEAR.php', 59a3dc3edaSGreg Roach 'pgv_to_wt.php', 60a3dc3edaSGreg Roach 'places', 61f397d0fdSGreg Roach //'robots.txt', // Do not delete this - it may contain user data 62a3dc3edaSGreg Roach 'serviceClientTest.php', 63a3dc3edaSGreg Roach 'siteconfig.php', 64a3dc3edaSGreg Roach 'SOAP', 65a3dc3edaSGreg Roach 'uploadmedia.php', 66a3dc3edaSGreg Roach 'useradmin.php', 67a3dc3edaSGreg Roach 'webservice', 68a3dc3edaSGreg Roach 'wtinfo.php', 69a3dc3edaSGreg Roach // Removed in 1.1.2 70a3dc3edaSGreg Roach 'treenav.php', 71a3dc3edaSGreg Roach // Removed in 1.2.3 7249a243cbSGreg Roach 'modules_v2', 73a3dc3edaSGreg Roach // Removed in 1.2.4 74a3dc3edaSGreg Roach 'search_engine.php', 75a3dc3edaSGreg Roach // Removed in 1.2.5 76a3dc3edaSGreg Roach 'sidebar.php', 77a3dc3edaSGreg Roach // Removed in 1.2.6 78a3dc3edaSGreg Roach // Removed in 1.2.7 79a3dc3edaSGreg Roach 'login_register.php', 80a3dc3edaSGreg Roach // Removed in 1.3.0 81a3dc3edaSGreg Roach 'admin_site_ipaddress.php', 82a3dc3edaSGreg Roach 'downloadgedcom.php', 83a3dc3edaSGreg Roach 'export_gedcom.php', 84a3dc3edaSGreg Roach 'gedcheck.php', 85a3dc3edaSGreg Roach 'images', 86a3dc3edaSGreg Roach // Removed in 1.3.1 87a3dc3edaSGreg Roach 'imageflush.php', 8849a243cbSGreg Roach '/lightbox/js/tip_balloon_RTL.js', 89a3dc3edaSGreg Roach // Removed in 1.4.0 90a3dc3edaSGreg Roach 'imageview.php', 91a3dc3edaSGreg Roach 'media/MediaInfo.txt', 92a3dc3edaSGreg Roach 'media/thumbs/ThumbsInfo.txt', 93a3dc3edaSGreg Roach // Removed in 1.5.3 94a3dc3edaSGreg Roach 'readme.html', 95a3dc3edaSGreg Roach // Removed in 1.6.0 96a3dc3edaSGreg Roach 'downloadbackup.php', 97a3dc3edaSGreg Roach 'site-php-version.php', 98a3dc3edaSGreg Roach // Removed in 1.7.0 99a3dc3edaSGreg Roach 'admin_site_other.php', 100a3dc3edaSGreg Roach 'js', 101a3dc3edaSGreg Roach 'library', 102a3dc3edaSGreg Roach 'save.php', 103a3dc3edaSGreg Roach // Removed in 1.7.2 104a3dc3edaSGreg Roach 'assets/js-1.7.0', 105a3dc3edaSGreg Roach // Removed in 1.7.4 106a3dc3edaSGreg Roach 'assets/js-1.7.2', 107a3dc3edaSGreg Roach // Removed in 1.7.7 108a3dc3edaSGreg Roach 'assets/js-1.7.4', 109a3dc3edaSGreg Roach // Removed in 2.0.0 110a3dc3edaSGreg Roach 'action.php', 111a3dc3edaSGreg Roach 'addmedia.php', 112a3dc3edaSGreg Roach 'addmin.php', 113a3dc3edaSGreg Roach 'admin_media.php', 114a3dc3edaSGreg Roach 'admin_media_upload.php', 115a3dc3edaSGreg Roach 'admin_module_blocks.php', 116a3dc3edaSGreg Roach 'admin_module_charts.php', 117a3dc3edaSGreg Roach 'admin_module_menus.php', 118a3dc3edaSGreg Roach 'admin_module_reports.php', 119a3dc3edaSGreg Roach 'admin_module_sidebar.php', 120a3dc3edaSGreg Roach 'admin_module_tabs.php', 121a3dc3edaSGreg Roach 'admin_modules.php', 122a3dc3edaSGreg Roach 'admin_pgv_to_wt.php', 123a3dc3edaSGreg Roach 'admin_site_access.php', 124a3dc3edaSGreg Roach 'admin_site_change.php', 125a3dc3edaSGreg Roach 'admin_site_clean.php', 126a3dc3edaSGreg Roach 'admin_site_config.php', 127a3dc3edaSGreg Roach 'admin_site_info.php', 128a3dc3edaSGreg Roach 'admin_site_logs.php', 129a3dc3edaSGreg Roach 'admin_site_merge.php', 130a3dc3edaSGreg Roach 'admin_site_readme.php', 131a3dc3edaSGreg Roach 'admin_site_upgrade.php', 132a3dc3edaSGreg Roach 'admin_trees_check.php', 133a3dc3edaSGreg Roach 'admin_trees_config.php', 134a3dc3edaSGreg Roach 'admin_trees_download.php', 135a3dc3edaSGreg Roach 'admin_trees_duplicates.php', 136a3dc3edaSGreg Roach 'admin_trees_export.php', 137a3dc3edaSGreg Roach 'admin_trees_manage.php', 138a3dc3edaSGreg Roach 'admin_trees_merge.php', 139a3dc3edaSGreg Roach 'admin_trees_places.php', 140a3dc3edaSGreg Roach 'admin_trees_renumber.php', 141a3dc3edaSGreg Roach 'admin_trees_unconnected.php', 142a3dc3edaSGreg Roach 'admin_users.php', 143a3dc3edaSGreg Roach 'admin_users_bulk.php', 144a3dc3edaSGreg Roach 'ancestry.php', 145a3dc3edaSGreg Roach 'app/Controller', 146a3dc3edaSGreg Roach 'app/HitCounter.php', 147a3dc3edaSGreg Roach 'app/Module/ClippingsCart/ClippingsCartController.php', 148a3dc3edaSGreg Roach 'app/Module/FamiliesSidebarModule.php', 149a3dc3edaSGreg Roach 'app/Module/FamilyTreeFavorites', 150a3dc3edaSGreg Roach 'app/Module/GoogleMaps', 151a3dc3edaSGreg Roach 'app/Module/IndividualSidebarModule.php', 152a3dc3edaSGreg Roach 'app/Module/PageMenuModule.php', 15380536c2dSGreg Roach 'app/Query', 154a3dc3edaSGreg Roach 'app/SpecialChars', 155a3dc3edaSGreg Roach 'assets/js-1.7.7', 156a3dc3edaSGreg Roach 'assets/js-1.7.9', 157a3dc3edaSGreg Roach 'autocomplete.php', 158a3dc3edaSGreg Roach 'block_edit.php', 159a3dc3edaSGreg Roach 'branches.php', 160a3dc3edaSGreg Roach 'calendar.php', 161a3dc3edaSGreg Roach 'compact.php', 162a3dc3edaSGreg Roach 'data/html_purifier_cache', 163a3dc3edaSGreg Roach 'descendancy.php', 164a3dc3edaSGreg Roach 'editnews.php', 165a3dc3edaSGreg Roach 'edituser.php', 166a3dc3edaSGreg Roach 'edit_changes.php', 167a3dc3edaSGreg Roach 'edit_interface.php', 168a3dc3edaSGreg Roach 'expand_view.php', 169a3dc3edaSGreg Roach 'familybook.php', 170a3dc3edaSGreg Roach 'famlist.php', 171a3dc3edaSGreg Roach 'fanchart.php', 172a3dc3edaSGreg Roach 'find.php', 173a3dc3edaSGreg Roach 'help_text.php', 174a3dc3edaSGreg Roach 'hourglass.php', 175a3dc3edaSGreg Roach 'hourglass_ajax.php', 176a3dc3edaSGreg Roach 'import.php', 177a3dc3edaSGreg Roach 'includes', 178a3dc3edaSGreg Roach 'index_edit.php', 179a3dc3edaSGreg Roach 'indilist.php', 180a3dc3edaSGreg Roach 'inverselink.php', 181362b8464SGreg Roach 'language', 182a3dc3edaSGreg Roach 'lifespan.php', 183a3dc3edaSGreg Roach 'login.php', 184a3dc3edaSGreg Roach 'logout.php', 185a3dc3edaSGreg Roach 'mediafirewall.php', 186a3dc3edaSGreg Roach 'medialist.php', 187a3dc3edaSGreg Roach 'message.php', 188a3dc3edaSGreg Roach 'module.php', 18949a243cbSGreg Roach 'modules_v3', 190a3dc3edaSGreg Roach 'notelist.php', 191a3dc3edaSGreg Roach 'packages', 192a3dc3edaSGreg Roach 'pedigree.php', 193a3dc3edaSGreg Roach 'relationship.php', 194a3dc3edaSGreg Roach 'repolist.php', 195a3dc3edaSGreg Roach 'reportengine.php', 196a3dc3edaSGreg Roach 'search.php', 197a3dc3edaSGreg Roach 'search_advanced.php', 198a3dc3edaSGreg Roach 'site-offline.php', 199a3dc3edaSGreg Roach 'site-unavailable.php', 200a3dc3edaSGreg Roach 'sourcelist.php', 201a3dc3edaSGreg Roach 'statistics.php', 202a3dc3edaSGreg Roach 'statisticsplot.php', 203acd79950SGreg Roach 'themes', 204a3dc3edaSGreg Roach 'timeline.php', 205acd79950SGreg Roach // Removed in 2.0.3 206acd79950SGreg Roach 'public/css/vendor.css', 207acd79950SGreg Roach // Removed in 2.0.4 208acd79950SGreg Roach 'public/favicon-120.png', 209acd79950SGreg Roach 'public/favicon-144.png', 210acd79950SGreg Roach 'public/favicon-57.png', 211acd79950SGreg Roach 'public/favicon-76.png', 212acd79950SGreg Roach 'public/favicon-96.png', 213acd79950SGreg Roach // Removed in 2.0.7 214acd79950SGreg Roach 'public/ckeditor-4.11.2-custom', 215acd79950SGreg Roach // Removed in 2.0.12 216acd79950SGreg Roach 'public/ckeditor-4.14.1-custom', 217acd79950SGreg Roach // Removed in 2.1.0 218acd79950SGreg Roach 'modules_v4/example-footer.disable', 219acd79950SGreg Roach 'modules_v4/example-middleware.disable', 220acd79950SGreg Roach 'modules_v4/example-report.disable', 221acd79950SGreg Roach 'modules_v4/example-report.disable', 222acd79950SGreg Roach 'modules_v4/example-server-configuration.disable', 223acd79950SGreg Roach 'modules_v4/example-theme.disable', 224acd79950SGreg Roach 'modules_v4/example.disable', 225acd79950SGreg Roach 'public/favicon-196.png', 226acd79950SGreg Roach 'public/site.webmanifest', 227a3dc3edaSGreg Roach ]; 228a3dc3edaSGreg Roach 229a3dc3edaSGreg Roach /** 230a3dc3edaSGreg Roach * Delete files and folders that belonged to an earlier version of webtrees. 231a3dc3edaSGreg Roach * Return a list of those that we could not delete. 232a3dc3edaSGreg Roach * 233f7cf8a15SGreg Roach * @param FilesystemOperator $filesystem 234a3dc3edaSGreg Roach * 235bfe98399SGreg Roach * @return array<string> 236a3dc3edaSGreg Roach */ 237f7cf8a15SGreg Roach public function deleteOldWebtreesFiles(FilesystemOperator $filesystem): array 238a3dc3edaSGreg Roach { 239a3dc3edaSGreg Roach $paths_to_delete = []; 240a3dc3edaSGreg Roach 241a3dc3edaSGreg Roach foreach (self::OLD_PATHS as $path) { 242a3dc3edaSGreg Roach if (!$this->deleteFileOrFolder($filesystem, $path)) { 243a3dc3edaSGreg Roach $paths_to_delete[] = $path; 244a3dc3edaSGreg Roach } 245a3dc3edaSGreg Roach } 246a3dc3edaSGreg Roach 247a3dc3edaSGreg Roach return $paths_to_delete; 248a3dc3edaSGreg Roach } 249a3dc3edaSGreg Roach 250a3dc3edaSGreg Roach /** 251a3dc3edaSGreg Roach * Delete old cache files. 252a3dc3edaSGreg Roach * 253f7cf8a15SGreg Roach * @param FilesystemOperator $filesystem 254c61566f9SGreg Roach * @param string $path 255c61566f9SGreg Roach * @param int $max_age Seconds 256c7ff4153SGreg Roach * 257c7ff4153SGreg Roach * @return void 258a3dc3edaSGreg Roach */ 259f7cf8a15SGreg Roach public function deleteOldFiles(FilesystemOperator $filesystem, string $path, int $max_age): void 260a3dc3edaSGreg Roach { 261d97083feSGreg Roach $threshold = time() - $max_age; 262e1357632SGreg Roach 263782714c2SGreg Roach $list = $filesystem->listContents($path, FilesystemReader::LIST_DEEP); 264a3dc3edaSGreg Roach 265a3dc3edaSGreg Roach foreach ($list as $metadata) { 266e1357632SGreg Roach // The timestamp can be absent or false. 267e1357632SGreg Roach $timestamp = $metadata['timestamp'] ?? false; 268e1357632SGreg Roach 269e1357632SGreg Roach if ($timestamp !== false && $timestamp < $threshold) { 270a3dc3edaSGreg Roach $this->deleteFileOrFolder($filesystem, $metadata['path']); 271a3dc3edaSGreg Roach } 272a3dc3edaSGreg Roach } 273a3dc3edaSGreg Roach } 274a3dc3edaSGreg Roach 275a3dc3edaSGreg Roach /** 276a3dc3edaSGreg Roach * @param int $max_age_in_seconds 277c7ff4153SGreg Roach * 278c7ff4153SGreg Roach * @return void 279a3dc3edaSGreg Roach */ 280e364afe4SGreg Roach public function deleteOldLogs(int $max_age_in_seconds): void 281a3dc3edaSGreg Roach { 282e5c19fcdSGreg Roach DB::table('log') 283e5c19fcdSGreg Roach ->whereIn('log_type', ['error', 'media']) 2843943950dSGreg Roach ->where('log_time', '<', date('Y-m-d H:i:s', time() - $max_age_in_seconds)) 285e5c19fcdSGreg Roach ->delete(); 286a3dc3edaSGreg Roach } 287a3dc3edaSGreg Roach 288a3dc3edaSGreg Roach /** 289a3dc3edaSGreg Roach * @param int $max_age_in_seconds 290c7ff4153SGreg Roach * 291c7ff4153SGreg Roach * @return void 292a3dc3edaSGreg Roach */ 293e364afe4SGreg Roach public function deleteOldSessions(int $max_age_in_seconds): void 294a3dc3edaSGreg Roach { 295e5c19fcdSGreg Roach DB::table('session') 2963943950dSGreg Roach ->where('session_time', '<', date('Y-m-d H:i:s', time() - $max_age_in_seconds)) 297e5c19fcdSGreg Roach ->delete(); 298a3dc3edaSGreg Roach } 299a3dc3edaSGreg Roach 300a3dc3edaSGreg Roach /** 301a3dc3edaSGreg Roach * Delete a file or folder, if we can. 302a3dc3edaSGreg Roach * 303f7cf8a15SGreg Roach * @param FilesystemOperator $filesystem 304a3dc3edaSGreg Roach * @param string $path 305a3dc3edaSGreg Roach * 306a3dc3edaSGreg Roach * @return bool 307a3dc3edaSGreg Roach */ 308f7cf8a15SGreg Roach private function deleteFileOrFolder(FilesystemOperator $filesystem, string $path): bool 309a3dc3edaSGreg Roach { 310a3dc3edaSGreg Roach try { 311a3dc3edaSGreg Roach $filesystem->delete($path); 31228d026adSGreg Roach } catch (FilesystemException | UnableToDeleteFile) { 313f32d77e6SGreg Roach try { 314f32d77e6SGreg Roach $filesystem->deleteDirectory($path); 31528d026adSGreg Roach } catch (FilesystemException | UnableToDeleteDirectory) { 316a3dc3edaSGreg Roach return false; 317a3dc3edaSGreg Roach } 318a3dc3edaSGreg Roach } 319a3dc3edaSGreg Roach 320a3dc3edaSGreg Roach return true; 321a3dc3edaSGreg Roach } 322a3dc3edaSGreg Roach} 323