first commit
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/site/VersionCheck.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class VersionCheck
|
||||
*
|
||||
* @ingroup site
|
||||
*
|
||||
* @see Version
|
||||
*
|
||||
* @brief Provides methods to check for the latest version of the application.
|
||||
*/
|
||||
|
||||
namespace PKP\site;
|
||||
|
||||
use APP\core\Application;
|
||||
use DateInterval;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use PKP\config\Config;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\file\FileManager;
|
||||
use SimpleXMLElement;
|
||||
|
||||
class VersionCheck
|
||||
{
|
||||
/** Max lifetime for the version cache */
|
||||
protected const MAX_CACHE_LIFETIME = '1 year';
|
||||
|
||||
public const VERSION_CODE_PATH = 'dbscripts/xml/version.xml';
|
||||
|
||||
/**
|
||||
* Return information about the latest available version.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getLatestVersion()
|
||||
{
|
||||
$application = Application::get();
|
||||
$includeId = Application::isInstalled() &&
|
||||
!Application::isUpgrading() &&
|
||||
Config::getVar('general', 'enable_beacon', true);
|
||||
|
||||
if ($includeId) {
|
||||
$uniqueSiteId = Application::get()->getUUID();
|
||||
} else {
|
||||
$uniqueSiteId = null;
|
||||
}
|
||||
|
||||
$request = $application->getRequest();
|
||||
return self::parseVersionXML(
|
||||
$application->getVersionDescriptorUrl() .
|
||||
($includeId ? '?id=' . urlencode($uniqueSiteId) .
|
||||
'&oai=' . urlencode($request->url('index', 'oai'))
|
||||
: '')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the currently installed database version.
|
||||
*
|
||||
* @return Version
|
||||
*/
|
||||
public static function getCurrentDBVersion()
|
||||
{
|
||||
$versionDao = DAORegistry::getDAO('VersionDAO'); /** @var VersionDAO $versionDao */
|
||||
return $versionDao->getCurrentVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current code version.
|
||||
*/
|
||||
public static function getCurrentCodeVersion(): ?Version
|
||||
{
|
||||
return self::parseVersionXML(self::VERSION_CODE_PATH)['version'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse information from a version XML file.
|
||||
*/
|
||||
public static function parseVersionXML(string $path): ?array
|
||||
{
|
||||
$isVirtual = FileManager::isVirtualPath($path);
|
||||
$key = __METHOD__ . static::MAX_CACHE_LIFETIME . $path . ($isVirtual ? '' : filemtime($path));
|
||||
$expiration = $isVirtual ? 0 : DateInterval::createFromDateString(static::MAX_CACHE_LIFETIME);
|
||||
$version = Cache::remember($key, $expiration, function () use ($path) {
|
||||
$xml = new SimpleXMLElement(FileManager::getStream($path));
|
||||
$version = [];
|
||||
foreach (['application', 'class', 'type', 'release', 'tag', 'date', 'info', 'package', 'lazy-load', 'sitewide'] as $name) {
|
||||
if (isset($xml->$name)) {
|
||||
$version[$name] = (string) $xml->$name;
|
||||
}
|
||||
}
|
||||
$version['sitewide'] = (int) ($version['sitewide'] ?? 0);
|
||||
$version['lazy-load'] = (int) ($version['lazy-load'] ?? 0);
|
||||
if (isset($xml->patch)) {
|
||||
$version['patch'] = [];
|
||||
foreach ($xml->patch as $patch) {
|
||||
$version['patch'][$patch['from']] = (string) $patch;
|
||||
}
|
||||
}
|
||||
return $version;
|
||||
});
|
||||
|
||||
// Built outside of the cache section to avoid serializing the Version (which would need a __set_state implementation)
|
||||
if (isset($version['release']) && isset($version['application'])) {
|
||||
$version['version'] = Version::fromString(
|
||||
$version['release'] ?? '',
|
||||
$version['type'] ?? '',
|
||||
$version['application'] ?? '',
|
||||
$version['class'] ?? '',
|
||||
$version['lazy-load'],
|
||||
$version['sitewide']
|
||||
);
|
||||
}
|
||||
return $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the applicable patch for the current code version (if available).
|
||||
*
|
||||
* @param array $versionInfo as returned by parseVersionXML()
|
||||
* @param Version $codeVersion as returned by getCurrentCodeVersion()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getPatch($versionInfo, $codeVersion = null)
|
||||
{
|
||||
if (!isset($codeVersion)) {
|
||||
$codeVersion = self::getCurrentCodeVersion();
|
||||
}
|
||||
if (isset($versionInfo['patch'][$codeVersion->getVersionString()])) {
|
||||
return $versionInfo['patch'][$codeVersion->getVersionString()];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given version file exists and whether it
|
||||
* contains valid data. Returns a Version object if everything
|
||||
* is ok, otherwise throws an Exception.
|
||||
*
|
||||
* @param string $versionFile
|
||||
*
|
||||
* @return Version
|
||||
*/
|
||||
public static function getValidPluginVersionInfo($versionFile)
|
||||
{
|
||||
$fileManager = new FileManager();
|
||||
if ($fileManager->fileExists($versionFile)) {
|
||||
$versionInfo = self::parseVersionXML($versionFile);
|
||||
} else {
|
||||
throw new Exception(__('manager.plugins.versionFileNotFound'));
|
||||
}
|
||||
|
||||
// Validate plugin name and type to avoid abuse
|
||||
$productType = explode('.', $versionInfo['type']);
|
||||
if (count($productType) != 2 || $productType[0] != 'plugins') {
|
||||
throw new Exception(__('manager.plugins.versionFileInvalid'));
|
||||
}
|
||||
|
||||
$pluginVersion = $versionInfo['version'];
|
||||
$namesToValidate = [$pluginVersion->getProduct(), $productType[1]];
|
||||
foreach ($namesToValidate as $nameToValidate) {
|
||||
if (!PKPString::regexp_match('/[a-z][a-zA-Z0-9]+/', $nameToValidate)) {
|
||||
throw new Exception(__('manager.plugins.versionFileInvalid'));
|
||||
}
|
||||
}
|
||||
|
||||
return $pluginVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the application's version against the latest version
|
||||
* on the PKP servers.
|
||||
*
|
||||
* @return string|false Version description or false if no newer version
|
||||
*/
|
||||
public static function checkIfNewVersionExists()
|
||||
{
|
||||
$versionInfo = self::getLatestVersion();
|
||||
$latestVersion = $versionInfo['release'];
|
||||
|
||||
$currentVersion = self::getCurrentDBVersion();
|
||||
if ($currentVersion->compare($latestVersion) < 0) {
|
||||
return $latestVersion;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\site\VersionCheck', '\VersionCheck');
|
||||
define('VERSION_CODE_PATH', VersionCheck::VERSION_CODE_PATH);
|
||||
}
|
||||
Reference in New Issue
Block a user