Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ The Joomla! 5.0 branch is under heavy development and not all links in this docu

Build Status
---------------------
| Drone-CI | AppVeyor | PHP | Node | npm |
|------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------| ------------- | ------------- |
| [![Build Status](https://ci.joomla.org/api/badges/joomla/joomla-cms/status.svg?branch=5.0-dev)](https://ci.joomla.org/joomla/joomla-cms) | [![Build status](https://ci.appveyor.com/api/projects/status/ru6sxal8jmfckvjc/branch/5.0-dev?svg=true)](https://ci.appveyor.com/project/release-joomla/joomla-cms) | [![PHP](https://img.shields.io/badge/PHP-V8.1.0-green)](https://www.php.net/) | [![node-lts](https://img.shields.io/badge/Node-V16.0-green)](https://nodejs.org/en/) | [![npm](https://img.shields.io/badge/npm-v8.6.0-green)](https://nodejs.org/en/) |
| Drone-CI | AppVeyor | PHP | Node | npm |
|------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|--------------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
| [![Build Status](https://ci.joomla.org/api/badges/joomla/joomla-cms/status.svg?branch=5.0-dev)](https://ci.joomla.org/joomla/joomla-cms) | [![Build status](https://ci.appveyor.com/api/projects/status/ru6sxal8jmfckvjc/branch/5.0-dev?svg=true)](https://ci.appveyor.com/project/release-joomla/joomla-cms) | [![PHP](https://img.shields.io/badge/PHP-V8.1.0-green)](https://www.php.net/) | [![node-lts](https://img.shields.io/badge/Node-V18.0-green)](https://nodejs.org/en/) | [![npm](https://img.shields.io/badge/npm-v9.6.7-green)](https://nodejs.org/en/) |

Overview
---------------------
Expand Down
124 changes: 97 additions & 27 deletions administrator/components/com_admin/script.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,50 @@ class JoomlaInstallerScript
*/
protected $fromVersion = null;

/**
* Callback for collecting errors. Like function(string $context, \Throwable $error){};
*
* @var callable
*
* @since __DEPLOY_VERSION__
*/
protected $errorCollector;

/**
* Set the callback for collecting errors.
*
* @param callable $callback The callback Like function(string $context, \Throwable $error){};
*
* @return void
*
* @since __DEPLOY_VERSION__
*/
public function setErrorCollector(callable $callback)
{
$this->errorCollector = $callback;
}

/**
* Collect errors.
*
* @param string $context A context/place where error happened
* @param \Throwable $error The error that occurred
*
* @return void
*
* @since __DEPLOY_VERSION__
*/
protected function collectError(string $context, \Throwable $error)
{
// The errorCollector are required
// However when someone already running the script manually the code may fail.
if ($this->errorCollector) {
call_user_func($this->errorCollector, $context, $error);
} else {
Log::add($error->getMessage(), Log::ERROR, 'Update');
}
}

/**
* Function to act prior to installation process begins
*
Expand Down Expand Up @@ -82,27 +126,45 @@ public function preflight($action, $installer)
*/
public function update($installer)
{
$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
$options['text_file'] = 'joomla_update.php';

Log::addLogger($options, Log::INFO, ['Update', 'databasequery', 'jerror']);

// Uninstall plugins before removing their files and folders
try {
Log::add(Text::_('COM_JOOMLAUPDATE_UPDATE_LOG_DELETE_FILES'), Log::INFO, 'Update');
} catch (RuntimeException $exception) {
// Informational log only
}

// Uninstall extensions before removing their files and folders
$this->uninstallExtensions();

// This needs to stay for 2.5 update compatibility
$this->deleteUnexistingFiles();
$this->updateManifestCaches();
$this->updateDatabase();
$this->updateAssets($installer);
$this->clearStatsCache();
$this->cleanJoomlaCache();
try {
Log::add(Text::_('COM_JOOMLAUPDATE_UPDATE_LOG_UNINSTALL_EXTENSIONS'), Log::INFO, 'Update');
$this->uninstallExtensions();
} catch (\Throwable $e) {
$this->collectError('uninstallExtensions', $e);
}

// Remove old files
try {
Log::add(Text::_('COM_JOOMLAUPDATE_UPDATE_LOG_DELETE_FILES'), Log::INFO, 'Update');
$this->deleteUnexistingFiles();
} catch (\Throwable $e) {
$this->collectError('deleteUnexistingFiles', $e);
}

// Further update
try {
$this->updateManifestCaches();
$this->updateDatabase();
$this->updateAssets($installer);
$this->clearStatsCache();
} catch (\Throwable $e) {
$this->collectError('Further update', $e);
}

// Clean cache
try {
$this->cleanJoomlaCache();
} catch (\Throwable $e) {
$this->collectError('cleanJoomlaCache', $e);
}
}

/**
Expand All @@ -127,7 +189,7 @@ protected function clearStatsCache()
->where($db->quoteName('element') . ' = ' . $db->quote('stats'))
)->loadResult();
} catch (Exception $e) {
echo Text::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br>';
$this->collectError(__METHOD__, $e);

return;
}
Expand All @@ -151,7 +213,7 @@ protected function clearStatsCache()
try {
$db->setQuery($query)->execute();
} catch (Exception $e) {
echo Text::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br>';
$this->collectError(__METHOD__, $e);

return;
}
Expand Down Expand Up @@ -183,7 +245,7 @@ protected function updateDatabaseMysql()
try {
$results = $db->loadObjectList();
} catch (Exception $e) {
echo Text::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br>';
$this->collectError(__METHOD__, $e);

return;
}
Expand All @@ -198,7 +260,7 @@ protected function updateDatabaseMysql()
try {
$db->execute();
} catch (Exception $e) {
echo Text::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br>';
$this->collectError(__METHOD__, $e);

return;
}
Expand Down Expand Up @@ -233,12 +295,12 @@ protected function uninstallExtensions()
* 'pre_function' => Name of an optional migration function to be called before
* uninstalling, `null` if not used.
*/
['type' => 'plugin', 'element' => 'demotasks', 'folder' => 'task', 'client_id' => 0, 'pre_function' => null],
['type' => 'plugin', 'element' => 'compat', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateCompatPlugin'],
['type' => 'plugin', 'element' => 'logrotation', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateLogRotationPlugin'],
['type' => 'plugin', 'element' => 'recaptcha', 'folder' => 'captcha', 'client_id' => 0, 'pre_function' => null],
['type' => 'plugin', 'element' => 'sessiongc', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateSessionGCPlugin'],
['type' => 'plugin', 'element' => 'updatenotification', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateUpdatenotificationPlugin'],
['type' => 'plugin', 'element' => 'demotasks', 'folder' => 'task', 'client_id' => 0, 'pre_function' => null],
['type' => 'plugin', 'element' => 'compat', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateCompatPlugin'],
['type' => 'plugin', 'element' => 'logrotation', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateLogRotationPlugin'],
['type' => 'plugin', 'element' => 'recaptcha', 'folder' => 'captcha', 'client_id' => 0, 'pre_function' => null],
['type' => 'plugin', 'element' => 'sessiongc', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateSessionGCPlugin'],
['type' => 'plugin', 'element' => 'updatenotification', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateUpdatenotificationPlugin'],
];

$db = Factory::getDbo();
Expand Down Expand Up @@ -477,7 +539,7 @@ protected function updateManifestCaches()
try {
$extensions = $db->loadObjectList();
} catch (Exception $e) {
echo Text::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '<br>';
$this->collectError(__METHOD__, $e);

return;
}
Expand All @@ -487,7 +549,10 @@ protected function updateManifestCaches()

foreach ($extensions as $extension) {
if (!$installer->refreshManifestCache($extension->extension_id)) {
echo Text::sprintf('FILES_JOOMLA_ERROR_MANIFEST', $extension->type, $extension->element, $extension->name, $extension->client_id) . '<br>';
$this->collectError(
__METHOD__,
new \Exception(Text::sprintf('FILES_JOOMLA_ERROR_MANIFEST', $extension->type, $extension->element, $extension->name, $extension->client_id))
);
}
}
}
Expand Down Expand Up @@ -2346,6 +2411,8 @@ public function updateAssets($installer)
$asset->setLocation(1, 'last-child');

if (!$asset->store()) {
$this->collectError(__METHOD__, new \Exception($asset->getError(true)));

// Install failed, roll back changes
$installer->abort(Text::sprintf('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK', $asset->getError(true)));

Expand Down Expand Up @@ -2552,6 +2619,9 @@ private function migratePrivacyconsentConfiguration(): bool
return false;
}

// Refresh versionable assets cache.
Factory::getApplication()->flushAssets();

return true;
}

Expand Down Expand Up @@ -2670,7 +2740,7 @@ private function setGuidedToursUid()
{
/** @var \Joomla\Component\Cache\Administrator\Model\CacheModel $model */
$model = Factory::getApplication()->bootComponent('com_guidedtours')->getMVCFactory()
->createModel('Tours', 'Administrator', ['ignore_request' => true]);
->createModel('Tours', 'Administrator', ['ignore_request' => true]);

$items = $model->getItems();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ public function display($cachable = false, $urlparams = false)
$view->setModel($warningsModel, false);
}

// Check for update result
if ($lName === 'complete') {
$state = $model->getState();
$state->set('update_finished_with_error', $this->app->getUserState('com_joomlaupdate.update_finished_with_error'));
$state->set('update_errors', (array) $this->app->getUserState('com_joomlaupdate.update_errors', []));
$state->set('installer_message', $this->app->getUserState('com_joomlaupdate.installer_message'));
$state->set('log_file', $this->app->get('log_path') . '/joomla_update.php');
}

// Perform update source preference check and refresh update information.
$model->applyUpdateSite();
$model->refreshUpdates();
Expand Down
Loading