10d11ac7eSGreg Roach<?php 20d11ac7eSGreg Roach/** 30d11ac7eSGreg Roach * webtrees: online genealogy 48fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team 50d11ac7eSGreg Roach * This program is free software: you can redistribute it and/or modify 60d11ac7eSGreg Roach * it under the terms of the GNU General Public License as published by 70d11ac7eSGreg Roach * the Free Software Foundation, either version 3 of the License, or 80d11ac7eSGreg Roach * (at your option) any later version. 90d11ac7eSGreg Roach * This program is distributed in the hope that it will be useful, 100d11ac7eSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 110d11ac7eSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 120d11ac7eSGreg Roach * GNU General Public License for more details. 130d11ac7eSGreg Roach * You should have received a copy of the GNU General Public License 140d11ac7eSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 150d11ac7eSGreg Roach */ 16e7f56f2aSGreg Roachdeclare(strict_types=1); 17e7f56f2aSGreg Roach 180d11ac7eSGreg Roachnamespace Fisharebest\Webtrees\Services; 190d11ac7eSGreg Roach 20*bf57b580SGreg Roachuse Carbon\Carbon; 210d11ac7eSGreg Roachuse Fisharebest\Webtrees\Site; 228d0ebef0SGreg Roachuse Fisharebest\Webtrees\Webtrees; 230d11ac7eSGreg Roachuse GuzzleHttp\Client; 240d11ac7eSGreg Roachuse GuzzleHttp\Exception\RequestException; 250d11ac7eSGreg Roachuse Symfony\Component\HttpFoundation\Response; 260d11ac7eSGreg Roach 270d11ac7eSGreg Roach/** 280d11ac7eSGreg Roach * Automatic upgrades. 290d11ac7eSGreg Roach */ 300d11ac7eSGreg Roachclass UpgradeService 310d11ac7eSGreg Roach{ 320d11ac7eSGreg Roach // Only check the webtrees server infrequently. 3316d6367aSGreg Roach private const CHECK_FOR_UPDATE_INTERVAL = 24 * 60 * 60; 340d11ac7eSGreg Roach 350d11ac7eSGreg Roach // Fetch information about upgrades from here. 360d11ac7eSGreg Roach // Note: earlier versions of webtrees used svn.webtrees.net, so we must maintain both URLs. 3716d6367aSGreg Roach private const UPDATE_URL = 'https://dev.webtrees.net/build/latest-version.txt'; 380d11ac7eSGreg Roach 390d11ac7eSGreg Roach // If the update server doesn't respond after this time, give up. 4016d6367aSGreg Roach private const HTTP_TIMEOUT = 3.0; 410d11ac7eSGreg Roach 420d11ac7eSGreg Roach /** 430d11ac7eSGreg Roach * @return bool 440d11ac7eSGreg Roach */ 450d11ac7eSGreg Roach public function isUpgradeAvailable(): bool 460d11ac7eSGreg Roach { 470d11ac7eSGreg Roach // If the latest version is unavailable, we will have an empty sting which equates to version 0. 480d11ac7eSGreg Roach 498d0ebef0SGreg Roach return version_compare(Webtrees::VERSION, $this->fetchLatestVersion()) < 0; 500d11ac7eSGreg Roach } 510d11ac7eSGreg Roach 520d11ac7eSGreg Roach /** 530d11ac7eSGreg Roach * What is the latest version of webtrees. 540d11ac7eSGreg Roach * 550d11ac7eSGreg Roach * @return string 560d11ac7eSGreg Roach */ 570d11ac7eSGreg Roach public function latestVersion(): string 580d11ac7eSGreg Roach { 590d11ac7eSGreg Roach $latest_version = $this->fetchLatestVersion(); 600d11ac7eSGreg Roach 6165e02381SGreg Roach [$version] = explode('|', $latest_version); 620d11ac7eSGreg Roach 630d11ac7eSGreg Roach return $version; 640d11ac7eSGreg Roach } 650d11ac7eSGreg Roach 660d11ac7eSGreg Roach /** 670d11ac7eSGreg Roach * Where can we download the latest version of webtrees. 680d11ac7eSGreg Roach * 690d11ac7eSGreg Roach * @return string 700d11ac7eSGreg Roach */ 710d11ac7eSGreg Roach public function downloadUrl(): string 720d11ac7eSGreg Roach { 730d11ac7eSGreg Roach $latest_version = $this->fetchLatestVersion(); 740d11ac7eSGreg Roach 7565e02381SGreg Roach [, , $url] = explode('|', $latest_version . '||'); 760d11ac7eSGreg Roach 770d11ac7eSGreg Roach return $url; 780d11ac7eSGreg Roach } 790d11ac7eSGreg Roach 800d11ac7eSGreg Roach /** 810d11ac7eSGreg Roach * Check with the webtrees.net server for the latest version of webtrees. 820d11ac7eSGreg Roach * Fetching the remote file can be slow, so check infrequently, and cache the result. 830d11ac7eSGreg Roach * Pass the current versions of webtrees, PHP and MySQL, as the response 840d11ac7eSGreg Roach * may be different for each. The server logs are used to generate 850d11ac7eSGreg Roach * installation statistics which can be found at http://dev.webtrees.net/statistics.html 860d11ac7eSGreg Roach * 870d11ac7eSGreg Roach * @return string 880d11ac7eSGreg Roach */ 890d11ac7eSGreg Roach private function fetchLatestVersion(): string 900d11ac7eSGreg Roach { 910d11ac7eSGreg Roach $last_update_timestamp = (int) Site::getPreference('LATEST_WT_VERSION_TIMESTAMP'); 920d11ac7eSGreg Roach 93*bf57b580SGreg Roach $current_timestamp = Carbon::now()->timestamp; 94*bf57b580SGreg Roach 95*bf57b580SGreg Roach if ($last_update_timestamp < $current_timestamp - self::CHECK_FOR_UPDATE_INTERVAL) { 960d11ac7eSGreg Roach try { 970d11ac7eSGreg Roach $client = new Client([ 980d11ac7eSGreg Roach 'timeout' => self::HTTP_TIMEOUT, 990d11ac7eSGreg Roach ]); 1000d11ac7eSGreg Roach 1010d11ac7eSGreg Roach $response = $client->get(self::UPDATE_URL, [ 1020d11ac7eSGreg Roach 'query' => $this->serverParameters(), 1030d11ac7eSGreg Roach ]); 1040d11ac7eSGreg Roach 1050d11ac7eSGreg Roach if ($response->getStatusCode() === Response::HTTP_OK) { 1060d11ac7eSGreg Roach Site::setPreference('LATEST_WT_VERSION', $response->getBody()->getContents()); 107*bf57b580SGreg Roach Site::setPreference('LATEST_WT_VERSION_TIMESTAMP', (string) $current_timestamp); 1080d11ac7eSGreg Roach } 1090d11ac7eSGreg Roach } catch (RequestException $ex) { 110c6a0ce5cSGreg Roach // Can't connect to the server? 111c6a0ce5cSGreg Roach // Use the existing information about latest versions. 1120d11ac7eSGreg Roach } 1130d11ac7eSGreg Roach } 1140d11ac7eSGreg Roach 1150d11ac7eSGreg Roach return Site::getPreference('LATEST_WT_VERSION'); 1160d11ac7eSGreg Roach } 1170d11ac7eSGreg Roach 1180d11ac7eSGreg Roach /** 1190d11ac7eSGreg Roach * The upgrade server needs to know a little about this server. 1200d11ac7eSGreg Roach */ 1218f53f488SRico Sonntag private function serverParameters(): array 1220d11ac7eSGreg Roach { 1230d11ac7eSGreg Roach $operating_system = DIRECTORY_SEPARATOR === '/' ? 'u' : 'w'; 1240d11ac7eSGreg Roach 1250d11ac7eSGreg Roach return [ 1268d0ebef0SGreg Roach 'w' => Webtrees::VERSION, 1270d11ac7eSGreg Roach 'p' => PHP_VERSION, 1280d11ac7eSGreg Roach 'o' => $operating_system, 1290d11ac7eSGreg Roach ]; 1300d11ac7eSGreg Roach } 1310d11ac7eSGreg Roach} 132