414 lines
9.7 KiB
PHP
414 lines
9.7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Vvveb
|
|
*
|
|
* Copyright (C) 2022 Ziadin Givan
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
namespace Vvveb\Controller\Tools;
|
|
|
|
use function Vvveb\__;
|
|
use function Vvveb\camelToUnderscore;
|
|
use Vvveb\Controller\Base;
|
|
use function Vvveb\humanReadable;
|
|
use Vvveb\System\Update as UpdateSys;
|
|
use Vvveb\System\User\Admin;
|
|
use function Vvveb\url;
|
|
|
|
class Update extends Base {
|
|
private $steps = ['checkPermissions', 'download', 'unzip', 'copyInstall', /*'backup',*/ 'copySystem', /* 'copyAdmin',*/ 'copyApp', 'copyCore', 'copyConfig', 'addNewColumns', 'createNewTables', 'copyPublic', 'copyPublicAdmin', 'copyPublicMedia', 'setFilePermissions', 'cleanUp', 'clearCache', 'complete'];
|
|
|
|
function __construct() {
|
|
$this->update = new UpdateSys();
|
|
}
|
|
|
|
private function checkUpdates($type = 'core', $force = false) {
|
|
$updateInfo = [];
|
|
$errorMsg = __('Error checking updates!');
|
|
|
|
try {
|
|
$updateInfo = $this->update->checkUpdates($type, $force);
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if (! $updateInfo) {
|
|
$this->view->errors[] = $errorMsg;
|
|
}
|
|
|
|
return $updateInfo;
|
|
}
|
|
|
|
function check() {
|
|
$type = $this->request->get['type'] ?? 'core';
|
|
$updateInfo = $this->update->checkUpdates($type, true);
|
|
|
|
if ($updateInfo) {
|
|
//$this->view->success[] = __('Check succesful!');
|
|
if ($updateInfo['hasUpdate']) {
|
|
$this->view->info[] = __('Updates available!') . ' <span class="badge bg-success">' . $updateInfo['version'] . '</span>';
|
|
} else {
|
|
$this->view->info[] = __('No updates available!');
|
|
}
|
|
}
|
|
|
|
return $this->index();
|
|
}
|
|
|
|
function updateNext() {
|
|
ignore_user_abort(true);
|
|
$step = $this->request->get['step'] ?? false;
|
|
$next = false;
|
|
|
|
if ($step && (($position = array_search($step, $this->steps)) !== false)) {
|
|
if (method_exists($this, $step) && $this->$step()) {
|
|
$position++;
|
|
$next = $this->steps[$position] ?? false;
|
|
} else {
|
|
$errorMsg = __('Failed at ') . $step;
|
|
$this->view->errors[] = $errorMsg;
|
|
$this->cleanUp();
|
|
}
|
|
}
|
|
|
|
$url = [];
|
|
|
|
if (isset($this->view->errors[0])) {
|
|
$url['error'] = $this->view->errors[0];
|
|
}
|
|
|
|
if (isset($this->view->success[0])) {
|
|
$url['success'] = $this->view->success[0];
|
|
}
|
|
|
|
if (isset($this->view->info[0])) {
|
|
$url['success'] = $this->view->info[0];
|
|
}
|
|
|
|
if ($next) {
|
|
$count = count($this->steps);
|
|
$url['info'] = sprintf(__('Step (%d/%d) %s ...'), $position, $count, humanReadable(camelToUnderscore($next)));
|
|
$this->view->info[] = $url['info'];
|
|
$url += ['module'=>'tools/update', 'action' => 'updateNext', 'step' => $next, 'position' => $position, 'count' => $count];
|
|
|
|
if ($this->request->isAjax()) {
|
|
die(json_encode($url + ['url' => url($url)]));
|
|
} else {
|
|
$this->redirect($url);
|
|
}
|
|
} else {
|
|
if ($position = count($this->steps)) {
|
|
$message = __('Update finished');
|
|
|
|
if ($this->request->isAjax()) {
|
|
die(json_encode($url + ['url' => url($url), 'success' => $message]));
|
|
} else {
|
|
$this->view->success[] = $message;
|
|
|
|
return $this->index();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private function download() {
|
|
$updateFile = false;
|
|
$errorDownloadMsg = __('Error downloading update!');
|
|
$updateInfo = $this->update->checkUpdates();
|
|
//don't load plugins during update to avoid possible conflicts
|
|
Admin::session(['safemode' => true]);
|
|
|
|
try {
|
|
$updateFile = $this->update->download($updateInfo['download']);
|
|
$this->session->set('updateFile', $updateFile);
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if (! $updateInfo || ! $updateFile) {
|
|
$this->view->errors[] = $errorDownloadMsg;
|
|
|
|
return false;
|
|
} else {
|
|
$this->view->info[] = $updateInfo['download'] . ' ' . __('downloaded successfully');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function checkPermissions() {
|
|
$result = false;
|
|
|
|
try {
|
|
$result = $this->update->checkPermissions();
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if ($result === true) {
|
|
$this->view->info[] = __('Permissions ok!');
|
|
} else {
|
|
$this->view->errors[] = sprintf(__('%s not writable!'), $result);
|
|
|
|
return false;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function backup() {
|
|
$result = false;
|
|
|
|
try {
|
|
$result = $this->update->backup();
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if ($result) {
|
|
$this->view->info[] = __('Backup successful!');
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function addNewColumns() {
|
|
$result = false;
|
|
|
|
try {
|
|
$result = $this->update->addNewColumns();
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if ($result) {
|
|
$this->view->info[] = __('Add new columns successful!');
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function createNewTables() {
|
|
$result = false;
|
|
|
|
try {
|
|
$result = $this->update->createNewTables();
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if ($result) {
|
|
$this->view->info[] = __('Create new tables successful!');
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function unzip() {
|
|
$errorInstallMsg = __('Error unzipping update!');
|
|
$result = true;
|
|
|
|
try {
|
|
$updateFile = $this->session->get('updateFile');
|
|
$result = $this->update->unzip($updateFile);
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if (! $result) {
|
|
$this->view->errors[] = $errorInstallMsg;
|
|
} else {
|
|
$this->view->success[] = __('Unzip successful!');
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
private function copy($method) {
|
|
$name = humanReadable(camelToUnderscore($method));
|
|
$errorInstallMsg = sprintf(__('Error updating %s'), $name);
|
|
$result = false;
|
|
|
|
$method = "copy$method";
|
|
|
|
try {
|
|
$result = $this->update->$method();
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if (! $result) {
|
|
$this->view->errors[] = $errorInstallMsg;
|
|
} else {
|
|
$this->view->success[] = sprintf(__('Update %s successful!'), $name);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function copyCore() {
|
|
return $this->copy('Core');
|
|
}
|
|
|
|
function copyConfig() {
|
|
return $this->copy('Config');
|
|
}
|
|
|
|
function copySystem() {
|
|
//merge system and admin in one step so that the updater does not break if depends on older system code.
|
|
$return = $this->copy('System');
|
|
|
|
if ($return) {
|
|
$return = $this->copy('Admin');
|
|
}
|
|
/*
|
|
//clear php cache to load new installer code
|
|
foreach ([DIR_SYSTEM . 'update.php', DIR_APP . 'controller' . DS . 'tools' . DS . 'update.php'] as $file) {
|
|
if (function_exists('opcache_invalidate')) {
|
|
opcache_invalidate($file);
|
|
}
|
|
clearstatcache(true, $file);
|
|
}
|
|
*/
|
|
return $return;
|
|
}
|
|
|
|
/*
|
|
function copyAdmin() {
|
|
return $this->copy('Admin');
|
|
}
|
|
*/
|
|
function copyApp() {
|
|
return $this->copy('App');
|
|
}
|
|
|
|
function copyInstall() {
|
|
return $this->copy('Install');
|
|
}
|
|
|
|
function copyPublic() {
|
|
return $this->copy('Public');
|
|
}
|
|
|
|
function copyPublicAdmin() {
|
|
return $this->copy('PublicAdmin');
|
|
}
|
|
|
|
function copyPublicMedia() {
|
|
return $this->copy('PublicMedia');
|
|
}
|
|
|
|
function setFilePermissions() {
|
|
$errorInstallMsg = __('Error setting permissions');
|
|
$result = false;
|
|
|
|
try {
|
|
$result = $this->update->setPermissions();
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if (! $result) {
|
|
$this->view->errors[] = $errorInstallMsg;
|
|
} else {
|
|
$this->view->success[] = __('Set permissions successful!');
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function cleanUp() {
|
|
$errorInstallMsg = __('Error cleaning up');
|
|
$result = false;
|
|
|
|
try {
|
|
$result = $this->update->cleanup();
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if (! $result) {
|
|
$this->view->errors[] = $errorInstallMsg;
|
|
} else {
|
|
$this->view->success[] = __('Cleanup successful!');
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function clearCache() {
|
|
$errorInstallMsg = __('Error clearing cache');
|
|
$result = false;
|
|
|
|
try {
|
|
$result = $this->update->clearCache();
|
|
} catch (\Exception $e) {
|
|
$this->view->errors[] = $e->getMessage();
|
|
}
|
|
|
|
if (! $result) {
|
|
$this->view->errors[] = $errorInstallMsg;
|
|
} else {
|
|
$this->view->success[] = __('Clear cache successful!');
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function complete() {
|
|
$this->view->success[] = __('Update complete!');
|
|
Admin::session(['safemode' => false]);
|
|
|
|
return true;
|
|
}
|
|
|
|
function update() {
|
|
$this->request->get['step'] = $this->steps[0];
|
|
$info = __('Update in progress, do not close this page ...');
|
|
$this->view->info[] = $info;
|
|
|
|
if ($this->request->isAjax()) {
|
|
$url = ['module'=>'tools/update', 'action' => 'updateNext', 'step' => $this->steps[0], 'position' => 0, 'count' => count($this->steps), 'info' => $info];
|
|
|
|
die(json_encode($url + ['url' => url($url)]));
|
|
} else {
|
|
$this->updateNext();
|
|
}
|
|
|
|
return $this->index();
|
|
}
|
|
|
|
function index() {
|
|
$updateInfo = $this->checkUpdates();
|
|
|
|
if (isset($updateInfo['error']) && $updateInfo['error']) {
|
|
$this->view->errors[] = $updateInfo['error'];
|
|
}
|
|
|
|
$info = [
|
|
'core' => [
|
|
'current' => V_VERSION,
|
|
'latest' => $updateInfo['version'] ?? '',
|
|
'hasUpdate' => $updateInfo['hasUpdate'] ?? false,
|
|
],
|
|
];
|
|
|
|
$this->view->update = $info;
|
|
}
|
|
}
|