From 1377ddb9abb178817751a62310ffb31fe00c5c0b Mon Sep 17 00:00:00 2001 From: Jan Stolle Date: Mon, 27 Oct 2025 15:47:13 +0100 Subject: [PATCH 1/6] Remove specific cache implementation dependency --- composer.json | 4 ++-- src/AutoUpdate.php | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 56be35b..7dca9b8 100755 --- a/composer.json +++ b/composer.json @@ -15,9 +15,9 @@ "ext-json": "*", "ext-zip": "*", "composer/semver": "^3.0", - "desarrolla2/cache": "^3.0", "monolog/monolog": "^2.1", - "psr/log": "^1.0|^2.0|^3.0" + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0" }, "require-dev": { "roave/security-advisories": "dev-master", diff --git a/src/AutoUpdate.php b/src/AutoUpdate.php index 426de09..16cdc24 100755 --- a/src/AutoUpdate.php +++ b/src/AutoUpdate.php @@ -3,12 +3,11 @@ namespace VisualAppeal; use Exception; +use Psr\SimpleCache\CacheInterface; use RuntimeException; use ZipArchive; use Composer\Semver\Comparator; -use Desarrolla2\Cache\CacheInterface; -use Desarrolla2\Cache\NotCache; use Monolog\Logger; use Psr\Log\LoggerInterface; use Psr\SimpleCache\InvalidArgumentException; @@ -36,9 +35,9 @@ class AutoUpdate { /** * Cache for update requests. * - * @var CacheInterface + * @var CacheInterface|null */ - private $cache; + private $cache = null; /** * Logger instance. @@ -205,9 +204,6 @@ public function __construct(?string $tempDir = null, ?string $installDir = null, $this->latestVersion = '0.0.0'; $this->currentVersion = '0.0.0'; - // Init cache - $this->cache = new NotCache(); - ini_set('max_execution_time', $maxExecutionTime); } @@ -449,7 +445,10 @@ public function checkUpdate(int $timeout = 10) $this->latestVersion = '0.0.0'; $this->updates = []; - $versions = $this->cache->get('update-versions'); + $versions = null; + if ($this->cache instanceof CacheInterface) { + $versions = $this->cache->get('update-versions'); + } // Create absolute url to update file $updateFile = $this->updateUrl . '/' . $this->updateFile; @@ -512,7 +511,9 @@ public function checkUpdate(int $timeout = 10) throw new ParserException(sprintf('Unknown file extension for update file %s!', $this->updateFile)); } - $this->cache->set('update-versions', $versions, $this->cacheTtl); + if ($this->cache instanceof CacheInterface) { + $this->cache->set('update-versions', $versions, $this->cacheTtl); + } } else { $this->log->debug('Got updates from cache'); } From 1daad074f750518b339f8a4538f85beab8a017b1 Mon Sep 17 00:00:00 2001 From: Jan Stolle Date: Mon, 27 Oct 2025 16:31:43 +0100 Subject: [PATCH 2/6] Bump php version to 8 This also adds types to all properties and functions --- .github/workflows/phpunit.yml | 2 +- composer.json | 2 +- src/AutoUpdate.php | 100 +++++++++------------------------- 3 files changed, 28 insertions(+), 76 deletions(-) diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 78041a6..0b54894 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - php-versions: ['7.3', '7.4', '8.0', '8.1'] + php-versions: ['8.0', '8.1', '8.2', '8.3', '8.4'] name: PHPUnit ${{ matrix.php-versions }} diff --git a/composer.json b/composer.json index 7dca9b8..b2292d8 100755 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ ], "minimum-stability": "stable", "require": { - "php": ">=7.2.0", + "php": ">=8.0", "ext-curl": "*", "ext-json": "*", "ext-zip": "*", diff --git a/src/AutoUpdate.php b/src/AutoUpdate.php index 16cdc24..dd2c9e1 100755 --- a/src/AutoUpdate.php +++ b/src/AutoUpdate.php @@ -20,136 +20,102 @@ class AutoUpdate { /** * The latest version. - * - * @var string */ - private $latestVersion; + private ?string $latestVersion; /** * Updates not yet installed. - * - * @var array */ - private $updates; + private array $updates; /** * Cache for update requests. - * - * @var CacheInterface|null */ - private $cache = null; + private ?CacheInterface $cache = null; /** * Logger instance. - * - * @var LoggerInterface */ - private $log; + private LoggerInterface $log; /** * Result of simulated installation. * * @var array */ - private $simulationResults = array(); + private array $simulationResults = array(); /** * Temporary download directory. - * - * @var string */ - private $tempDir = ''; + private string $tempDir = ''; /** * Install directory. - * - * @var string */ - private $installDir = ''; + private string $installDir = ''; /** * Update branch. - * - * @var string */ - private $branch = ''; + private string $branch = ''; /** * Username authentication - * - * @var string */ - private $username = ''; + private string $username = ''; /** * Password authentication - * - * @var string */ - private $password = ''; + private string $password = ''; - /* + /** * Callbacks to be called when each update is finished - * - * @var array */ - private $onEachUpdateFinishCallbacks = []; + private array $onEachUpdateFinishCallbacks = []; - /* + /** * Callbacks to be called when all updates are finished - * - * @var array */ - private $onAllUpdateFinishCallbacks = []; + private array $onAllUpdateFinishCallbacks = []; /** * If curl should verify the host certificate. - * - * @var bool */ - private $sslVerifyHost = true; + private bool $sslVerifyHost = true; /** * Url to the update folder on the server. - * - * @var string */ - protected $updateUrl = 'https://example.com/updates/'; + protected string $updateUrl = 'https://example.com/updates/'; /** * Version filename on the server. - * - * @var string */ - protected $updateFile = 'update.json'; + protected string $updateFile = 'update.json'; /** * Current version. - * - * @var string */ - protected $currentVersion; + protected string $currentVersion = ''; /** * Create new folders with these privileges. * * @var int */ - public $dirPermissions = 0755; + public int $dirPermissions = 0755; /** * Update script filename. - * - * @var string */ - public $updateScriptName = '_upgrade.php'; + public string $updateScriptName = '_upgrade.php'; /** * How long the cache should be valid (in seconds). - * - * @var int */ - protected $cacheTtl = 3600; + protected int $cacheTtl = 3600; /** * No update available. @@ -285,11 +251,8 @@ public function setUpdateUrl(string $updateUrl): AutoUpdate /** * Set the update branch. - * - * @param string branch - * @return AutoUpdate */ - public function setBranch($branch): AutoUpdate + public function setBranch(string $branch): AutoUpdate { $this->branch = $branch; @@ -298,10 +261,6 @@ public function setBranch($branch): AutoUpdate /** * Set the cache component. - * - * @param CacheInterface $adapter See https://github.com/desarrolla2/Cache - * @param int $ttl - * @return AutoUpdate */ public function setCache(CacheInterface $adapter, int $ttl): AutoUpdate { @@ -313,9 +272,6 @@ public function setCache(CacheInterface $adapter, int $ttl): AutoUpdate /** * Set the version of the current installed software. - * - * @param string $currentVersion - * @return AutoUpdate */ public function setCurrentVersion(string $currentVersion): AutoUpdate { @@ -326,10 +282,6 @@ public function setCurrentVersion(string $currentVersion): AutoUpdate /** * Set username and password for basic authentication. - * - * @param string $username - * @param string $password - * @return AutoUpdate */ public function setBasicAuth(string $username, string $password): AutoUpdate { @@ -437,7 +389,7 @@ public function setSslVerifyHost(bool $sslVerifyHost): AutoUpdate * @throws InvalidArgumentException * @throws ParserException */ - public function checkUpdate(int $timeout = 10) + public function checkUpdate(int $timeout = 10): bool|int { $this->log->notice('Checking for a new update...'); @@ -497,7 +449,7 @@ public function checkUpdate(int $timeout = 10) break; case 'json': - $versions = (array) json_decode($update, false); + $versions = json_decode($update, true); if (!is_array($versions)) { $this->log->error('Unable to parse json update file!'); @@ -586,7 +538,7 @@ protected function isValidUrl(string $url): bool * @param int $timeout * @return string|false */ - protected function downloadCurl(string $url, int $timeout = 10) + protected function downloadCurl(string $url, int $timeout = 10): bool|string { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); @@ -857,7 +809,7 @@ protected function install(string $updateFile, bool $simulateInstall, string $ve * @throws ParserException * @throws InvalidArgumentException */ - public function update(bool $simulateInstall = true, bool $deleteDownload = true) + public function update(bool $simulateInstall = true, bool $deleteDownload = true): bool|int { $this->log->info('Trying to perform update'); From 0103739ae9693961f34accb285d63f0afbc7631a Mon Sep 17 00:00:00 2001 From: Jan Stolle Date: Mon, 27 Oct 2025 16:36:09 +0100 Subject: [PATCH 3/6] Run rector with PHP 8 rules --- example/client/update/index.php | 4 +--- src/AutoUpdate.php | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/example/client/update/index.php b/example/client/update/index.php index 86ca478..0b85c13 100755 --- a/example/client/update/index.php +++ b/example/client/update/index.php @@ -28,9 +28,7 @@ echo 'New Version: ' . $update->getLatestVersion() . '
'; echo 'Installing Updates:
'; echo '
';
-    var_dump(array_map(function ($version) {
-        return (string) $version;
-    }, $update->getVersionsToUpdate()));
+    var_dump(array_map(fn($version) => (string) $version, $update->getVersionsToUpdate()));
     echo '
'; // Optional - empty log file diff --git a/src/AutoUpdate.php b/src/AutoUpdate.php index dd2c9e1..5b0d5db 100755 --- a/src/AutoUpdate.php +++ b/src/AutoUpdate.php @@ -43,7 +43,7 @@ class AutoUpdate { * * @var array */ - private array $simulationResults = array(); + private array $simulationResults = []; /** * Temporary download directory. @@ -299,11 +299,11 @@ public function setBasicAuth(string $username, string $password): AutoUpdate private function useBasicAuth() { if ($this->username && $this->password) { - return stream_context_create(array( - 'http' => array( + return stream_context_create([ + 'http' => [ 'header' => "Authorization: Basic " . base64_encode("$this->username:$this->password") - ) - )); + ] + ]); } return null; @@ -340,9 +340,7 @@ public function getLatestVersion(): string public function getVersionsToUpdate(): array { if (count($this->updates) > 0) { - return array_map(static function ($update) { - return $update['version']; - }, $this->updates); + return array_map(static fn($update) => $update['version'], $this->updates); } return []; @@ -443,9 +441,7 @@ public function checkUpdate(int $timeout = 10): bool|int throw new ParserException(sprintf('Could not parse update ini file %s!', $this->updateFile)); } - $versions = array_map(static function ($block) { - return $block['url'] ?? false; - }, $versions); + $versions = array_map(static fn($block) => $block['url'] ?? false, $versions); break; case 'json': @@ -757,10 +753,10 @@ protected function install(string $updateFile, bool $simulateInstall, string $ve // Read every file from archive for ($i = 0; $i < $zip->numFiles; $i++) { $fileStats = $zip->statIndex($i); - $filename = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $fileStats['name']); - $foldername = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, + $filename = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $fileStats['name']); + $foldername = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $this->installDir . dirname($filename)); - $absoluteFilename = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->installDir . $filename); + $absoluteFilename = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $this->installDir . $filename); $this->log->debug(sprintf('Updating file "%s"', $filename)); if (!is_dir($foldername) && !mkdir($foldername, $this->dirPermissions, true) && !is_dir($foldername)) { From 0e83c41e34e68c376f86e75518e1ec2ade95731e Mon Sep 17 00:00:00 2001 From: Jan Stolle Date: Tue, 28 Oct 2025 08:22:13 +0100 Subject: [PATCH 4/6] Refactor phpunit configuration Also add .idea folder to gitignore --- .gitignore | 2 ++ composer.json | 2 +- phpunit.xml | 27 +++++++++++++++++++++++++++ tests/AutoUpdateTest.php | 3 +++ tests/UnitTests.xml | 7 ------- 5 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 phpunit.xml delete mode 100755 tests/UnitTests.xml diff --git a/.gitignore b/.gitignore index 6d5428f..06a61a7 100755 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ *.cache composer.lock + +.idea/ diff --git a/composer.json b/composer.json index b2292d8..ecad576 100755 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ } }, "scripts": { - "test": "phpunit -c tests/UnitTests.xml" + "test": "phpunit" }, "config": { "sort-packages": true diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..c0f096b --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,27 @@ + + + + + tests + + + + + + src + + + diff --git a/tests/AutoUpdateTest.php b/tests/AutoUpdateTest.php index d01bc0f..92243a6 100755 --- a/tests/AutoUpdateTest.php +++ b/tests/AutoUpdateTest.php @@ -8,6 +8,9 @@ use VisualAppeal\Exceptions\DownloadException; use VisualAppeal\Exceptions\ParserException; +/** + * @covers \VisualAppeal\AutoUpdate + */ class AutoUpdateTest extends TestCase { /** diff --git a/tests/UnitTests.xml b/tests/UnitTests.xml deleted file mode 100755 index 7e6fc02..0000000 --- a/tests/UnitTests.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - ./ - - - From 81138150a0d543bbd43d368fb3b6b9e1def034f5 Mon Sep 17 00:00:00 2001 From: Jan Stolle Date: Tue, 28 Oct 2025 08:31:03 +0100 Subject: [PATCH 5/6] Make Logger optional and remove Monolog --- composer.json | 6 +-- src/AutoUpdate.php | 116 ++++++++++++++++++++++----------------------- 2 files changed, 59 insertions(+), 63 deletions(-) diff --git a/composer.json b/composer.json index ecad576..5589e82 100755 --- a/composer.json +++ b/composer.json @@ -15,13 +15,13 @@ "ext-json": "*", "ext-zip": "*", "composer/semver": "^3.0", - "monolog/monolog": "^2.1", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0" }, "require-dev": { - "roave/security-advisories": "dev-master", - "phpunit/phpunit": "^9.5" + "monolog/monolog": "^3.9", + "phpunit/phpunit": "^9.5", + "roave/security-advisories": "dev-master" }, "autoload": { "psr-4": { diff --git a/src/AutoUpdate.php b/src/AutoUpdate.php index 5b0d5db..7479c0f 100755 --- a/src/AutoUpdate.php +++ b/src/AutoUpdate.php @@ -8,7 +8,6 @@ use ZipArchive; use Composer\Semver\Comparator; -use Monolog\Logger; use Psr\Log\LoggerInterface; use Psr\SimpleCache\InvalidArgumentException; use VisualAppeal\Exceptions\DownloadException; @@ -36,7 +35,7 @@ class AutoUpdate { /** * Logger instance. */ - private LoggerInterface $log; + private ?LoggerInterface $log = null; /** * Result of simulated installation. @@ -161,9 +160,6 @@ class AutoUpdate { */ public function __construct(?string $tempDir = null, ?string $installDir = null, int $maxExecutionTime = 60) { - // Init logger - $this->log = new Logger('auto-update'); - $this->setTempDir($tempDir ?? (__DIR__ . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR)); $this->setInstallDir($installDir ?? (__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR)); @@ -184,10 +180,10 @@ public function setTempDir(string $dir): bool $dir = $this->addTrailingSlash($dir); if (!is_dir($dir)) { - $this->log->debug(sprintf('Creating new temporary directory "%s"', $dir)); + $this->log?->debug(sprintf('Creating new temporary directory "%s"', $dir)); if (!mkdir($dir, 0755, true) && !is_dir($dir)) { - $this->log->critical(sprintf('Could not create temporary directory "%s"', $dir)); + $this->log?->critical(sprintf('Could not create temporary directory "%s"', $dir)); return false; } @@ -209,10 +205,10 @@ public function setInstallDir(string $dir): bool $dir = $this->addTrailingSlash($dir); if (!is_dir($dir)) { - $this->log->debug(sprintf('Creating new install directory "%s"', $dir)); + $this->log?->debug(sprintf('Creating new install directory "%s"', $dir)); if (!mkdir($dir, 0755, true) && !is_dir($dir)) { - $this->log->critical(sprintf('Could not create install directory "%s"', $dir)); + $this->log?->critical(sprintf('Could not create install directory "%s"', $dir)); return false; } @@ -389,7 +385,7 @@ public function setSslVerifyHost(bool $sslVerifyHost): AutoUpdate */ public function checkUpdate(int $timeout = 10): bool|int { - $this->log->notice('Checking for a new update...'); + $this->log?->notice('Checking for a new update...'); // Reset previous updates $this->latestVersion = '0.0.0'; @@ -408,14 +404,14 @@ public function checkUpdate(int $timeout = 10): bool|int // Check if cache is empty if ($versions === null || $versions === false) { - $this->log->debug(sprintf('Get new updates from %s', $updateFile)); + $this->log?->debug(sprintf('Get new updates from %s', $updateFile)); // Read update file from update server if (function_exists('curl_version') && $this->isValidUrl($updateFile)) { $update = $this->downloadCurl($updateFile, $timeout); if ($update === false) { - $this->log->error(sprintf('Could not download update file "%s" via curl!', $updateFile)); + $this->log?->error(sprintf('Could not download update file "%s" via curl!', $updateFile)); throw new DownloadException($updateFile); } @@ -423,7 +419,7 @@ public function checkUpdate(int $timeout = 10): bool|int $update = @file_get_contents($updateFile, false, $this->useBasicAuth()); if ($update === false) { - $this->log->error(sprintf('Could not download update file "%s" via file_get_contents!', + $this->log?->error(sprintf('Could not download update file "%s" via file_get_contents!', $updateFile)); throw new DownloadException($updateFile); @@ -436,7 +432,7 @@ public function checkUpdate(int $timeout = 10): bool|int case 'ini': $versions = parse_ini_string($update, true); if (!is_array($versions)) { - $this->log->error('Unable to parse ini update file!'); + $this->log?->error('Unable to parse ini update file!'); throw new ParserException(sprintf('Could not parse update ini file %s!', $this->updateFile)); } @@ -447,14 +443,14 @@ public function checkUpdate(int $timeout = 10): bool|int case 'json': $versions = json_decode($update, true); if (!is_array($versions)) { - $this->log->error('Unable to parse json update file!'); + $this->log?->error('Unable to parse json update file!'); throw new ParserException(sprintf('Could not parse update json file %s!', $this->updateFile)); } break; default: - $this->log->error(sprintf('Unknown file extension "%s"', $updateFileExtension)); + $this->log?->error(sprintf('Unknown file extension "%s"', $updateFileExtension)); throw new ParserException(sprintf('Unknown file extension for update file %s!', $this->updateFile)); } @@ -463,11 +459,11 @@ public function checkUpdate(int $timeout = 10): bool|int $this->cache->set('update-versions', $versions, $this->cacheTtl); } } else { - $this->log->debug('Got updates from cache'); + $this->log?->debug('Got updates from cache'); } if (!is_array($versions)) { - $this->log->error(sprintf('Could not read versions from server %s', $updateFile)); + $this->log?->error(sprintf('Could not read versions from server %s', $updateFile)); return false; } @@ -496,12 +492,12 @@ public function checkUpdate(int $timeout = 10): bool|int }); if ($this->newVersionAvailable()) { - $this->log->debug(sprintf('New version "%s" available', $this->latestVersion)); + $this->log?->debug(sprintf('New version "%s" available', $this->latestVersion)); return true; } - $this->log->debug('No new version available'); + $this->log?->debug('No new version available'); return self::NO_UPDATE_AVAILABLE; } @@ -548,7 +544,7 @@ protected function downloadCurl(string $url, int $timeout = 10): bool|string $success = true; if (curl_error($curl)) { $success = false; - $this->log->error(sprintf( + $this->log?->error(sprintf( 'Could not download update "%s" via curl: %s!', $url, curl_error($curl) @@ -570,7 +566,7 @@ protected function downloadCurl(string $url, int $timeout = 10): bool|string */ protected function downloadUpdate(string $updateUrl, string $updateFile): bool { - $this->log->info(sprintf('Downloading update "%s" to "%s"', $updateUrl, $updateFile)); + $this->log?->info(sprintf('Downloading update "%s" to "%s"', $updateUrl, $updateFile)); if (function_exists('curl_version') && $this->isValidUrl($updateUrl)) { $update = $this->downloadCurl($updateUrl); if ($update === false) { @@ -580,7 +576,7 @@ protected function downloadUpdate(string $updateUrl, string $updateFile): bool $update = @file_get_contents($updateUrl, false, $this->useBasicAuth()); if ($update === false) { - $this->log->error(sprintf('Could not download update "%s"!', $updateUrl)); + $this->log?->error(sprintf('Could not download update "%s"!', $updateUrl)); throw new DownloadException($updateUrl); } @@ -590,13 +586,13 @@ protected function downloadUpdate(string $updateUrl, string $updateFile): bool $handle = fopen($updateFile, 'wb'); if (!$handle) { - $this->log->error(sprintf('Could not open file handle to save update to "%s"!', $updateFile)); + $this->log?->error(sprintf('Could not open file handle to save update to "%s"!', $updateFile)); return false; } if (!fwrite($handle, $update)) { - $this->log->error(sprintf('Could not write update to file "%s"!', $updateFile)); + $this->log?->error(sprintf('Could not write update to file "%s"!', $updateFile)); fclose($handle); return false; @@ -615,14 +611,14 @@ protected function downloadUpdate(string $updateUrl, string $updateFile): bool */ protected function simulateInstall(string $updateFile): bool { - $this->log->notice('[SIMULATE] Install new version'); + $this->log?->notice('[SIMULATE] Install new version'); clearstatcache(); // Check if zip file could be opened $zip = new ZipArchive(); $resource = $zip->open($updateFile); if ($resource !== true) { - $this->log->error(sprintf('Could not open zip file "%s", error: %d', $updateFile, $resource)); + $this->log?->error(sprintf('Could not open zip file "%s", error: %d', $updateFile, $resource)); return false; } @@ -642,14 +638,14 @@ protected function simulateInstall(string $updateFile): bool 'absolute_filename' => $absoluteFilename, ]; - $this->log->debug(sprintf('[SIMULATE] Updating file "%s"', $filename)); + $this->log?->debug(sprintf('[SIMULATE] Updating file "%s"', $filename)); // Check if parent directory is writable if (!is_dir($foldername)) { if (!mkdir($foldername) && !is_dir($foldername)) { throw new RuntimeException(sprintf('Directory "%s" was not created', $foldername)); } - $this->log->debug(sprintf('[SIMULATE] Create directory "%s"', $foldername)); + $this->log?->debug(sprintf('[SIMULATE] Create directory "%s"', $foldername)); $files[$i]['parent_folder_exists'] = false; $parent = dirname($foldername); @@ -657,7 +653,7 @@ protected function simulateInstall(string $updateFile): bool $files[$i]['parent_folder_writable'] = false; $simulateSuccess = false; - $this->log->warning(sprintf('[SIMULATE] Directory "%s" has to be writeable!', $parent)); + $this->log?->warning(sprintf('[SIMULATE] Directory "%s" has to be writeable!', $parent)); } else { $files[$i]['parent_folder_writable'] = true; } @@ -675,7 +671,7 @@ protected function simulateInstall(string $updateFile): bool $files[$i]['file_writable'] = false; $simulateSuccess = false; - $this->log->warning(sprintf('[SIMULATE] Could not overwrite "%s"!', $absoluteFilename)); + $this->log?->warning(sprintf('[SIMULATE] Could not overwrite "%s"!', $absoluteFilename)); } } else { $files[$i]['file_exists'] = false; @@ -685,7 +681,7 @@ protected function simulateInstall(string $updateFile): bool $files[$i]['file_writable'] = false; $simulateSuccess = false; - $this->log->warning(sprintf('[SIMULATE] The file "%s" could not be created!', + $this->log?->warning(sprintf('[SIMULATE] The file "%s" could not be created!', $absoluteFilename)); } else { $files[$i]['file_writable'] = true; @@ -693,12 +689,12 @@ protected function simulateInstall(string $updateFile): bool } else { $files[$i]['file_writable'] = true; - $this->log->debug(sprintf('[SIMULATE] The file "%s" could be created', $absoluteFilename)); + $this->log?->debug(sprintf('[SIMULATE] The file "%s" could be created', $absoluteFilename)); } } if ($filename === $this->updateScriptName) { - $this->log->debug(sprintf('[SIMULATE] Update script "%s" found', $absoluteFilename)); + $this->log?->debug(sprintf('[SIMULATE] Update script "%s" found', $absoluteFilename)); $files[$i]['update_script'] = true; } else { $files[$i]['update_script'] = false; @@ -722,17 +718,17 @@ protected function simulateInstall(string $updateFile): bool */ protected function install(string $updateFile, bool $simulateInstall, string $version): bool { - $this->log->notice(sprintf('Trying to install update "%s"', $updateFile)); + $this->log?->notice(sprintf('Trying to install update "%s"', $updateFile)); // Check if install should be simulated if ($simulateInstall) { if ($this->simulateInstall($updateFile)) { - $this->log->notice(sprintf('Simulation of update "%s" process succeeded', $version)); + $this->log?->notice(sprintf('Simulation of update "%s" process succeeded', $version)); return true; } - $this->log->critical(sprintf('Simulation of update "%s" process failed!', $version)); + $this->log?->critical(sprintf('Simulation of update "%s" process failed!', $version)); return self::ERROR_SIMULATE; } @@ -745,7 +741,7 @@ protected function install(string $updateFile, bool $simulateInstall, string $ve $zip = new ZipArchive(); $resource = $zip->open($updateFile); if ($resource !== true) { - $this->log->error(sprintf('Could not open zip file "%s", error: %d', $updateFile, $resource)); + $this->log?->error(sprintf('Could not open zip file "%s", error: %d', $updateFile, $resource)); return false; } @@ -757,10 +753,10 @@ protected function install(string $updateFile, bool $simulateInstall, string $ve $foldername = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $this->installDir . dirname($filename)); $absoluteFilename = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $this->installDir . $filename); - $this->log->debug(sprintf('Updating file "%s"', $filename)); + $this->log?->debug(sprintf('Updating file "%s"', $filename)); if (!is_dir($foldername) && !mkdir($foldername, $this->dirPermissions, true) && !is_dir($foldername)) { - $this->log->error(sprintf('Directory "%s" has to be writeable!', $foldername)); + $this->log?->error(sprintf('Directory "%s" has to be writeable!', $foldername)); return false; } @@ -772,25 +768,25 @@ protected function install(string $updateFile, bool $simulateInstall, string $ve // Extract file if ($zip->extractTo($this->installDir, $fileStats['name']) === false) { - $this->log->error(sprintf('Could not read zip entry "%s"', $fileStats['name'])); + $this->log?->error(sprintf('Could not read zip entry "%s"', $fileStats['name'])); continue; } //If file is a update script, include if ($filename === $this->updateScriptName) { - $this->log->debug(sprintf('Try to include update script "%s"', $absoluteFilename)); + $this->log?->debug(sprintf('Try to include update script "%s"', $absoluteFilename)); require($absoluteFilename); - $this->log->info(sprintf('Update script "%s" included!', $absoluteFilename)); + $this->log?->info(sprintf('Update script "%s" included!', $absoluteFilename)); if (!unlink($absoluteFilename)) { - $this->log->warning(sprintf('Could not delete update script "%s"!', $absoluteFilename)); + $this->log?->warning(sprintf('Could not delete update script "%s"!', $absoluteFilename)); } } } $zip->close(); - $this->log->notice(sprintf('Update "%s" successfully installed', $version)); + $this->log?->notice(sprintf('Update "%s" successfully installed', $version)); return true; } @@ -807,7 +803,7 @@ protected function install(string $updateFile, bool $simulateInstall, string $ve */ public function update(bool $simulateInstall = true, bool $deleteDownload = true): bool|int { - $this->log->info('Trying to perform update'); + $this->log?->info('Trying to perform update'); // Check for latest version if ($this->latestVersion === null || count($this->updates) === 0) { @@ -815,24 +811,24 @@ public function update(bool $simulateInstall = true, bool $deleteDownload = true } if ($this->latestVersion === null || count($this->updates) === 0) { - $this->log->error('Could not get latest version from server!'); + $this->log?->error('Could not get latest version from server!'); return self::ERROR_VERSION_CHECK; } // Check if current version is up-to-date if (!$this->newVersionAvailable()) { - $this->log->warning('No update available!'); + $this->log?->warning('No update available!'); return self::NO_UPDATE_AVAILABLE; } foreach ($this->updates as $update) { - $this->log->debug(sprintf('Update to version "%s"', $update['version'])); + $this->log?->debug(sprintf('Update to version "%s"', $update['version'])); // Check for temp directory if (empty($this->tempDir) || !is_dir($this->tempDir) || !is_writable($this->tempDir)) { - $this->log->critical(sprintf('Temporary directory "%s" does not exist or is not writeable!', + $this->log?->critical(sprintf('Temporary directory "%s" does not exist or is not writeable!', $this->tempDir)); return self::ERROR_TEMP_DIR; @@ -840,7 +836,7 @@ public function update(bool $simulateInstall = true, bool $deleteDownload = true // Check for install directory if (empty($this->installDir) || !is_dir($this->installDir) || !is_writable($this->installDir)) { - $this->log->critical(sprintf('Install directory "%s" does not exist or is not writeable!', + $this->log?->critical(sprintf('Install directory "%s" does not exist or is not writeable!', $this->installDir)); return self::ERROR_INSTALL_DIR; @@ -851,15 +847,15 @@ public function update(bool $simulateInstall = true, bool $deleteDownload = true // Download update if (!is_file($updateFile)) { if (!$this->downloadUpdate($update['url'], $updateFile)) { - $this->log->critical(sprintf('Failed to download update from "%s" to "%s"!', $update['url'], + $this->log?->critical(sprintf('Failed to download update from "%s" to "%s"!', $update['url'], $updateFile)); return self::ERROR_DOWNLOAD_UPDATE; } - $this->log->debug(sprintf('Latest update downloaded to "%s"', $updateFile)); + $this->log?->debug(sprintf('Latest update downloaded to "%s"', $updateFile)); } else { - $this->log->info(sprintf('Latest update already downloaded to "%s"', $updateFile)); + $this->log?->info(sprintf('Latest update already downloaded to "%s"', $updateFile)); } // Install update @@ -867,12 +863,12 @@ public function update(bool $simulateInstall = true, bool $deleteDownload = true if ($result === true) { $this->runOnEachUpdateFinishCallbacks($update['version'], $simulateInstall); if ($deleteDownload) { - $this->log->debug(sprintf('Trying to delete update file "%s" after successfull update', + $this->log?->debug(sprintf('Trying to delete update file "%s" after successfull update', $updateFile)); if (unlink($updateFile)) { - $this->log->info(sprintf('Update file "%s" deleted after successfull update', $updateFile)); + $this->log?->info(sprintf('Update file "%s" deleted after successfull update', $updateFile)); } else { - $this->log->error(sprintf('Could not delete update file "%s" after successfull update!', + $this->log?->error(sprintf('Could not delete update file "%s" after successfull update!', $updateFile)); return self::ERROR_DELETE_TEMP_UPDATE; @@ -880,11 +876,11 @@ public function update(bool $simulateInstall = true, bool $deleteDownload = true } } else { if ($deleteDownload) { - $this->log->debug(sprintf('Trying to delete update file "%s" after failed update', $updateFile)); + $this->log?->debug(sprintf('Trying to delete update file "%s" after failed update', $updateFile)); if (unlink($updateFile)) { - $this->log->info(sprintf('Update file "%s" deleted after failed update', $updateFile)); + $this->log?->info(sprintf('Update file "%s" deleted after failed update', $updateFile)); } else { - $this->log->error(sprintf('Could not delete update file "%s" after failed update!', + $this->log?->error(sprintf('Could not delete update file "%s" after failed update!', $updateFile)); } } From 54ea1b7837cec9d05e87e822c853532966293f14 Mon Sep 17 00:00:00 2001 From: Jan Stolle Date: Tue, 28 Oct 2025 09:21:57 +0100 Subject: [PATCH 6/6] Fix the type errors suggested by PHPStan level 5 --- src/AutoUpdate.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/AutoUpdate.php b/src/AutoUpdate.php index 7479c0f..5d2cb98 100755 --- a/src/AutoUpdate.php +++ b/src/AutoUpdate.php @@ -20,7 +20,7 @@ class AutoUpdate { /** * The latest version. */ - private ?string $latestVersion; + private string $latestVersion; /** * Updates not yet installed. @@ -534,7 +534,7 @@ protected function downloadCurl(string $url, int $timeout = 10): bool|string { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->sslVerifyHost ? 2 : 0); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->sslVerifyHost); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5); @@ -714,9 +714,9 @@ protected function simulateInstall(string $updateFile): bool * @param string $updateFile Path to the update file * @param bool $simulateInstall Check for directory and file permissions instead of installing the update * @param string $version - * @return bool + * @return bool|int */ - protected function install(string $updateFile, bool $simulateInstall, string $version): bool + protected function install(string $updateFile, bool $simulateInstall, string $version): bool|int { $this->log?->notice(sprintf('Trying to install update "%s"', $updateFile)); @@ -806,11 +806,11 @@ public function update(bool $simulateInstall = true, bool $deleteDownload = true $this->log?->info('Trying to perform update'); // Check for latest version - if ($this->latestVersion === null || count($this->updates) === 0) { + if (count($this->updates) === 0) { $this->checkUpdate(); } - if ($this->latestVersion === null || count($this->updates) === 0) { + if (count($this->updates) === 0) { $this->log?->error('Could not get latest version from server!'); return self::ERROR_VERSION_CHECK;