From 5ff9d13450f467d6b16262074d00194fd70def2c Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 10:08:56 +0100 Subject: [PATCH 001/130] Add extension class to joomlaupdater --- .../src/Extension/JoomlaupdateComponent.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php new file mode 100644 index 0000000000000..6d93923eb3021 --- /dev/null +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -0,0 +1,26 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Administrator\Extension; + +use Joomla\CMS\Extension\MVCComponent; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Component class for com_config + * + * @since __DEPLOY_VERSION__ + */ +class JoomlaupdateComponent extends MVCComponent +{ +} From d73c89ac0d5ac5842ca53c7893eea12211d73d88 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 11:12:15 +0100 Subject: [PATCH 002/130] Allow components to change config form --- .../com_config/src/Model/ComponentModel.php | 29 +++++++++++++++ .../src/Config/ConfigServiceInterface.php | 34 ++++++++++++++++++ libraries/src/Config/ConfigServiceTrait.php | 36 +++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 libraries/src/Config/ConfigServiceInterface.php create mode 100644 libraries/src/Config/ConfigServiceTrait.php diff --git a/administrator/components/com_config/src/Model/ComponentModel.php b/administrator/components/com_config/src/Model/ComponentModel.php index 17554c5791631..08a5a44892a38 100644 --- a/administrator/components/com_config/src/Model/ComponentModel.php +++ b/administrator/components/com_config/src/Model/ComponentModel.php @@ -13,6 +13,7 @@ use Joomla\CMS\Access\Access; use Joomla\CMS\Access\Rules; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Config\ConfigServiceInterface; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; @@ -101,6 +102,34 @@ public function getForm($data = [], $loadData = true) return $form; } + /** + * Method to preprocess the form. + * + * @param Form $form A Form object. + * @param mixed $data The data expected for the form. + * @param string $group The name of the plugin group to import. + * + * @return void + * + * @since __DEPLOY_VERSION__ + * + * @throws \Exception if there is an error in the form event. + * + * @see \Joomla\CMS\Form\FormField + */ + protected function preprocessForm(Form $form, $data, $group = 'content') + { + $component = $this->getState()->get('component.option'); + + $componentInterface = Factory::getApplication()->bootComponent($component); + + if ($componentInterface instanceof ConfigServiceInterface) { + $componentInterface->prepareForm($form, $data); + } + + parent::preprocessForm($form, $data, $group); + } + /** * Method to get the data that should be injected in the form. * diff --git a/libraries/src/Config/ConfigServiceInterface.php b/libraries/src/Config/ConfigServiceInterface.php new file mode 100644 index 0000000000000..097c32c2b6bde --- /dev/null +++ b/libraries/src/Config/ConfigServiceInterface.php @@ -0,0 +1,34 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Config; + +use Joomla\CMS\Form\Form; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Allows manipulating the config form for this component. + * + * @since __DEPLOY_VERSION__ + */ +interface ConfigServiceInterface +{ + /** + * Prepares the config form + * + * @param Form $form The form to change + * @param array|object $data The form data + * + * @return void + */ + public function prepareForm(Form $form, $data) : void; +} diff --git a/libraries/src/Config/ConfigServiceTrait.php b/libraries/src/Config/ConfigServiceTrait.php new file mode 100644 index 0000000000000..acdc03c1731d6 --- /dev/null +++ b/libraries/src/Config/ConfigServiceTrait.php @@ -0,0 +1,36 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Config; + +use Joomla\CMS\Form\Form; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Trait for component categories service. + * + * @since __DEPLOY_VERSION__ + */ +trait ConfigServiceTrait +{ + /** + * Prepares the config form + * + * @param Form $form The form to change + * @param array|object $data The form data + * + * @return void + */ + public function prepareForm(Form $form, $data) : void + { + } +} From 4168ed1ecca6b8b503d0788b8e0654472d4ea29e Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 11:19:00 +0100 Subject: [PATCH 003/130] Add extension class for joomlaupdater --- .../components/com_joomlaupdate/services/provider.php | 4 ++-- .../src/Extension/JoomlaupdateComponent.php | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/administrator/components/com_joomlaupdate/services/provider.php b/administrator/components/com_joomlaupdate/services/provider.php index b55a04a784520..ae4bb2ddec2f4 100644 --- a/administrator/components/com_joomlaupdate/services/provider.php +++ b/administrator/components/com_joomlaupdate/services/provider.php @@ -12,10 +12,10 @@ use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface; use Joomla\CMS\Extension\ComponentInterface; -use Joomla\CMS\Extension\MVCComponent; use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory; use Joomla\CMS\Extension\Service\Provider\MVCFactory; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\Component\Joomlaupdate\Administrator\Extension\JoomlaupdateComponent; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; @@ -42,7 +42,7 @@ public function register(Container $container) $container->set( ComponentInterface::class, function (Container $container) { - $component = new MVCComponent($container->get(ComponentDispatcherFactoryInterface::class)); + $component = new JoomlaupdateComponent($container->get(ComponentDispatcherFactoryInterface::class)); $component->setMVCFactory($container->get(MVCFactoryInterface::class)); diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php index 6d93923eb3021..670a68652da09 100644 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -10,7 +10,13 @@ namespace Joomla\Component\Joomlaupdate\Administrator\Extension; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Config\ConfigServiceInterface; +use Joomla\CMS\Config\ConfigServiceTrait; use Joomla\CMS\Extension\MVCComponent; +use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; +use Joomla\CMS\User\UserHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -21,6 +27,7 @@ * * @since __DEPLOY_VERSION__ */ -class JoomlaupdateComponent extends MVCComponent +class JoomlaupdateComponent extends MVCComponent implements ConfigServiceInterface { + use ConfigServiceTrait; } From 6f72404da7d18d0e6900b764e1ee2281d6bd34f5 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 11:19:37 +0100 Subject: [PATCH 004/130] Add needed config fields for automated updates --- .../components/com_joomlaupdate/config.xml | 34 +++++++++++++++++++ .../language/en-GB/com_joomlaupdate.ini | 11 ++++++ 2 files changed, 45 insertions(+) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index feb77e4a5abd4..6b645e89d22c1 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -72,4 +72,38 @@ +
+ + + + + + + +
diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 66daf5ab8fdb9..7d9d31651ec27 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -5,16 +5,27 @@ COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." +COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_DESC="Define which releases you want automated updates for. Note: Automated updates are only available for minor and patch releases." +COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_LABEL="Automated updates" +COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_DESC="Automatically update Joomla to the latest version when it is available." +COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_LABEL="Automated Update" +COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_MINOR="Minor + Patch Releases" +COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_NONE="None" +COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_PATCH="Patch Releases" COM_JOOMLAUPDATE_CONFIG_BACKUPCHECK_DESC="Shows the checkbox to confirm you have taken a backup and you're ready to update in the final step before the update is actually applied." COM_JOOMLAUPDATE_CONFIG_BACKUPCHECK_LABEL="Confirm Backup Checkbox" COM_JOOMLAUPDATE_CONFIG_CUSTOMURL_LABEL="Custom URL" COM_JOOMLAUPDATE_CONFIG_SOURCES_DESC="Configure where Joomla gets its update information from." COM_JOOMLAUPDATE_CONFIG_SOURCES_LABEL="Update Source" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM="Custom URL" +COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_LABEL="Last checked" +COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_DESC="The last time the automated update server could reach this site. If this date is too old, something is wrong with the automated update and you should re-initiate the process by saving the configuration." COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM_ERROR="The custom URL field is empty." COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_DEFAULT="Default" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_LABEL="Update Channel" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_NEXT="Joomla Next" +COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_DESC="This is the update token that Joomla uses to authenticate with the Joomla Update Server. It is used to ensure that only your site can update itself." +COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_LABEL="Update Token" ; Deprecated, will be removed with 6.0 COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_TESTING="Testing" COM_JOOMLAUPDATE_CONFIG_VERSIONCHECK_DESC="Shows the checkbox in the pre–update check if any of the extensions installed on your site is potentially incompatible with the version of Joomla you are upgrading to. Note: the checkbox is displayed when upgrading to a new Joomla version family (minor or major version)." From 0c304017420f03bb0e045bf92486b88c2112be8e Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 11:40:04 +0100 Subject: [PATCH 005/130] Add initial joomlaupdate webservice plugin --- .../en-GB/plg_webservices_joomlaupdate.ini | 7 ++ .../plg_webservices_joomlaupdate.sys.ini | 7 ++ .../webservices/joomlaupdate/joomlaupdate.xml | 21 ++++++ .../joomlaupdate/services/provider.php | 46 +++++++++++++ .../src/Extension/Joomlaupdate.php | 64 +++++++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 administrator/language/en-GB/plg_webservices_joomlaupdate.ini create mode 100644 administrator/language/en-GB/plg_webservices_joomlaupdate.sys.ini create mode 100644 plugins/webservices/joomlaupdate/joomlaupdate.xml create mode 100644 plugins/webservices/joomlaupdate/services/provider.php create mode 100644 plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php diff --git a/administrator/language/en-GB/plg_webservices_joomlaupdate.ini b/administrator/language/en-GB/plg_webservices_joomlaupdate.ini new file mode 100644 index 0000000000000..8b4adddcd014b --- /dev/null +++ b/administrator/language/en-GB/plg_webservices_joomlaupdate.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2024 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +PLG_WEBSERVICES_JOOMLAUPDATE="Web Services - Joomlaupdate" +PLG_WEBSERVICES_JOOMLAUPDATE_XML_DESCRIPTION="Add Joomlaupdate routes to the API for your website." diff --git a/administrator/language/en-GB/plg_webservices_joomlaupdate.sys.ini b/administrator/language/en-GB/plg_webservices_joomlaupdate.sys.ini new file mode 100644 index 0000000000000..8b4adddcd014b --- /dev/null +++ b/administrator/language/en-GB/plg_webservices_joomlaupdate.sys.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2024 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +PLG_WEBSERVICES_JOOMLAUPDATE="Web Services - Joomlaupdate" +PLG_WEBSERVICES_JOOMLAUPDATE_XML_DESCRIPTION="Add Joomlaupdate routes to the API for your website." diff --git a/plugins/webservices/joomlaupdate/joomlaupdate.xml b/plugins/webservices/joomlaupdate/joomlaupdate.xml new file mode 100644 index 0000000000000..0dafe3650471c --- /dev/null +++ b/plugins/webservices/joomlaupdate/joomlaupdate.xml @@ -0,0 +1,21 @@ + + + plg_webservices_joomlaupdate + Joomla! Project + 2024-11 + (C) 2024 Open Source Matters, Inc. + GNU General Public License version 2 or later; see LICENSE.txt + admin@joomla.org + www.joomla.org + 5.0.0 + PLG_WEBSERVICES_JOOMLAUPDATE_XML_DESCRIPTION + Joomla\Plugin\WebServices\Joomlaupdate + + services + src + + + language/en-GB/plg_webservices_joomlaupdate.ini + language/en-GB/plg_webservices_joomlaupdate.sys.ini + + diff --git a/plugins/webservices/joomlaupdate/services/provider.php b/plugins/webservices/joomlaupdate/services/provider.php new file mode 100644 index 0000000000000..aaa31dc1dc446 --- /dev/null +++ b/plugins/webservices/joomlaupdate/services/provider.php @@ -0,0 +1,46 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +\defined('_JEXEC') or die; + +use Joomla\CMS\Extension\PluginInterface; +use Joomla\CMS\Factory; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; +use Joomla\Plugin\WebServices\Joomlaupdate\Extension\Joomlaupdate; + +return new class () implements ServiceProviderInterface { + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * + * @since 4.4.0 + */ + public function register(Container $container): void + { + $container->set( + PluginInterface::class, + function (Container $container) { + $plugin = new Joomlaupdate( + $container->get(DispatcherInterface::class), + (array) PluginHelper::getPlugin('webservices', 'joomlaupdate') + ); + $plugin->setApplication(Factory::getApplication()); + + return $plugin; + } + ); + } +}; diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php new file mode 100644 index 0000000000000..28049c4997c28 --- /dev/null +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -0,0 +1,64 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Plugin\WebServices\Joomlaupdate\Extension; + +use Joomla\CMS\Event\Application\BeforeApiRouteEvent; +use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\Event\SubscriberInterface; +use Joomla\Router\Route; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Web Services adapter for com_joomlaupdate. + * + * @since __DEPLOY_VERSION__ + */ +final class Joomlaupdate extends CMSPlugin implements SubscriberInterface +{ + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onBeforeApiRoute' => 'onBeforeApiRoute', + ]; + } + + /** + * Registers com_joomlaupdate's API's routes in the application + * + * @param BeforeApiRouteEvent $event The event object + * + * @return void + * + * @since 4.0.0 + */ + public function onBeforeApiRoute(BeforeApiRouteEvent $event): void + { + $router = $event->getRouter(); + + $defaults = ['component' => 'com_joomlaupdate', 'public' => true]; + + $routes = [ + new Route(['GET'], 'v1/joomlaupdate', 'manage.healthCheck', [], $defaults), + ]; + + $router->addRoutes($routes); + } +} From 6f1fc7ca60dd51fab6b7442344e0e720740a1add Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 13:18:11 +0100 Subject: [PATCH 006/130] Implement healthcheck API --- .../src/Controller/HealthcheckController.php | 170 ++++++++++++++++++ .../src/View/Healthcheck/JsonapiView.php | 73 ++++++++ .../src/Extension/Joomlaupdate.php | 2 +- 3 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 api/components/com_joomlaupdate/src/Controller/HealthcheckController.php create mode 100644 api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php new file mode 100644 index 0000000000000..f20a1624baffb --- /dev/null +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -0,0 +1,170 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Api\Controller; + +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\Controller\ApiController; +use Tobscure\JsonApi\Exception\InvalidParameterException; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * The healthcheck controller + * + * @since __DEPLOY_VERSION__ + */ +class HealthcheckController extends ApiController +{ + /** + * The content type of the item. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $contentType = 'healthcheck'; + + /** + * The default view for the display method. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $default_view = 'healthcheck'; + + public function show() + { + $this->validateUpdateToken(); + + $viewType = $this->app->getDocument()->getType(); + $viewName = $this->input->get('view', $this->default_view); + $viewLayout = $this->input->get('layout', 'default', 'string'); + + try { + /** @var JsonApiView $view */ + $view = $this->getView( + $viewName, + $viewType, + '', + ['base_path' => $this->basePath, 'layout' => $viewLayout, 'contentType' => $this->contentType] + ); + } catch (\Exception $e) { + throw new \RuntimeException($e->getMessage()); + } + + $modelName = $this->input->get('model', $this->contentType); + + /** @var ListModel $model */ + $model = $this->getModel('Update', 'Administrator', ['ignore_request' => true, 'state' => $this->modelState]); + + if (!$model) { + throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_MODEL_CREATE')); + } + + // Push the model into the view (as default) + $view->setModel($model, true); + + $view->setDocument($this->app->getDocument()); + + $view->healthCheck(); + + return $this; + } + + /** + * Basic display of an item view. We don't allow this + * + * @param integer $id The primary key to display. Leave empty if you want to retrieve data from the request + * + * @return static A \JControllerLegacy object to support chaining. + * + * @since __DEPLOY_VERSION__ + */ + public function displayItem($id = null) + { + throw new \RuntimeException('Not implemented', 501); + } + + /** + * List view amended to add filtering of data. We don't allow this + * + * @return static A BaseController object to support chaining. + * + * @since __DEPLOY_VERSION__ + */ + public function displayList() + { + throw new \RuntimeException('Not implemented', 501); + } + + /** + * Removes an item. + * + * @param integer $id The primary key to delete item. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function delete($id = null) + { + throw new \RuntimeException('Not implemented', 501); + } + + /** + * Method to check if you can edit an existing record. + * + * We don't allow editing from API (yet?) + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key; default is id. + * + * @return boolean + * + * @since __DEPLOY_VERSION__ + */ + protected function allowEdit($data = [], $key = 'id') + { + return false; + } + + /** + * Method to check if you can add a new record. + * + * We don't allow adding from API + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since __DEPLOY_VERSION__ + */ + protected function allowAdd($data = []) + { + return false; + } + + protected function validateUpdateToken() : void { + $token = $this->input->get('token', $this->input->get->get('token'), 'STRING'); + + if (empty($token)) { + throw new InvalidParameterException('Token is required', 403, null, 'token'); + } + + $config = ComponentHelper::getParams('com_joomlaupdate'); + + if ($config->get('update_token') !== $token) { + throw new InvalidParameterException('Invalid token', 403, null, 'token'); + } + } +} diff --git a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php new file mode 100644 index 0000000000000..0b9bd8e298484 --- /dev/null +++ b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php @@ -0,0 +1,73 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Api\View\Healthcheck; + +use Joomla\CMS\Factory; +use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; +use Joomla\CMS\Uri\Uri; +use Joomla\Database\DatabaseInterface; +use Tobscure\JsonApi\Resource; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * The healthcheck view + * + * @since __DEPLOY_VERSION__ + */ +class JsonapiView extends BaseApiView +{ + /** + * Get the data that will be sent to the update server. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + protected function getStatsData() + { + $db = Factory::getContainer()->get(DatabaseInterface::class); + + $data = [ + 'php_version' => PHP_VERSION, + 'db_type' => $db->name, + 'db_version' => $db->getVersion(), + 'cms_version' => JVERSION, + 'server_os' => php_uname('s') . ' ' . php_uname('r'), + ]; + + // Check if we have a MariaDB version string and extract the proper version from it + if (preg_match('/^(?:5\.5\.5-)?(mariadb-)?(?P\d+)\.(?P\d+)\.(?P\d+)/i', $data['db_version'], $versionParts)) { + $data['db_version'] = $versionParts['major'] . '.' . $versionParts['minor'] . '.' . $versionParts['patch']; + } + + return $data; + } + + /** + * Generates the health check output + * + * @return void + */ + public function healthCheck() { + $data = $this->getStatsData(); + + $element = (new Resource($data, $this->serializer)) + ->fields(['healthcheck' => ['php_version', 'db_type', 'db_version', 'cms_version', 'server_os']]); + + $this->getDocument()->setData($element); + $this->getDocument()->addLink('self', Uri::current()); + + return $this->getDocument()->render(); + } +} diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index 28049c4997c28..e220bb26bb0b7 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -56,7 +56,7 @@ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void $defaults = ['component' => 'com_joomlaupdate', 'public' => true]; $routes = [ - new Route(['GET'], 'v1/joomlaupdate', 'manage.healthCheck', [], $defaults), + new Route(['GET'], 'v1/joomlaupdate/healthcheck', 'healthcheck.show', [], $defaults), ]; $router->addRoutes($routes); From 39d91f29c79de9abfbaf6dbcdc448681648c6be2 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 13:24:45 +0100 Subject: [PATCH 007/130] Move token check to header --- .../com_joomlaupdate/src/Controller/HealthcheckController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index f20a1624baffb..a9b06408de648 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -155,7 +155,7 @@ protected function allowAdd($data = []) } protected function validateUpdateToken() : void { - $token = $this->input->get('token', $this->input->get->get('token'), 'STRING'); + $token = $this->input->server->get('HTTP_X_JUPDATE_TOKEN', '', 'STRING'); if (empty($token)) { throw new InvalidParameterException('Token is required', 403, null, 'token'); From a8c8a3b78354e9c727719a26752d9c67697c0c39 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 13:48:38 +0100 Subject: [PATCH 008/130] Update last health check date in extension table --- .../src/Model/UpdateModel.php | 23 +++++++++++++++++++ .../src/Controller/HealthcheckController.php | 3 +++ 2 files changed, 26 insertions(+) diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index 430b28db8f451..0896c0cc414c4 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -25,6 +25,7 @@ use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\BaseDatabaseModel; use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Table\Extension; use Joomla\CMS\Table\Tuf as TufMetadata; use Joomla\CMS\Updater\Update; use Joomla\CMS\Updater\Updater; @@ -457,6 +458,28 @@ public function download() return $response; } + /** + * Update the datetime for the last health check run + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function updateLastHealthCheck() { + $extension = new Extension($this->getDatabase()); + + $extensionId = $extension->find(['element' => 'com_joomlaupdate']); + + $extension->load($extensionId); + + $params = new Registry($extension->params); + $params->set('update_last_check', Factory::getDate()->toSql()); + + $extension->params = (string) $params; + + $extension->store(); + } + /** * Return the result of the checksum of a package with the SHA256/SHA384/SHA512 tags in the update server manifest * diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index a9b06408de648..b8e286f74e4e1 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -78,6 +78,9 @@ public function show() $view->healthCheck(); + // If we reach this point, healthcheck was successful, so update the date in the config + $model->updateLastHealthCheck(); + return $this; } From fe935e57b70ede6e2a2717c34a3d6b33eea8d4f1 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 14:02:24 +0100 Subject: [PATCH 009/130] Implement token generation on config save --- .../components/com_joomlaupdate/config.xml | 2 +- .../src/Extension/JoomlaupdateComponent.php | 71 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index 6b645e89d22c1..dc64cdc0defb5 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -99,7 +99,7 @@ /> getName() !== 'com_config.component') + { + return; + } + + // We remove the token field, if no auto update is selected + if (empty($data['autoupdate']) || !in_array($data['autoupdate'], ['minor', 'patch'])) + { + $form->removeField('update_token'); + } + // If we want automated updates, check if we have an old key to use otherwise generate a new one (don't use the submited one, if could be manipulated) + else { + $config = ComponentHelper::getParams('com_joomlaupdate'); + + $token = $config->get('update_token'); + + if (empty($token)) + { + $token = UserHelper::genRandomPassword(40); + } + + $form->setFieldAttribute('update_token', 'default', $token); + } + + // Handle automated updates when form is submitted (but before it's saved) + $input = Factory::getApplication()->getInput(); + + if ($input->getMethod() === 'POST') + { + $this->manageAutoUpdate($data); + } + } + + /** + * Decide if we subscribe or unsubscribe from automated updates + * + * @param array|object $data + * + * @return void + */ + protected function manageAutoUpdate($data) { + if (empty($data['autoupdate']) || !in_array($data['autoupdate'], ['minor', 'patch'])) + { + $config = ComponentHelper::getParams('com_joomlaupdate'); + + $token = $config->get('update_token'); + + if ($token) { + // @todo implement + // $this->autoUpdateUnsubscribe($token); + } + + return; + } + + // @todo implement + // $this->autoUpdateSubscribe($data); + } } From 102f6a5f8967146137e11d7a129dcd67cb771d3f Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 14:09:24 +0100 Subject: [PATCH 010/130] Add deploy version --- plugins/webservices/joomlaupdate/services/provider.php | 2 +- plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/webservices/joomlaupdate/services/provider.php b/plugins/webservices/joomlaupdate/services/provider.php index aaa31dc1dc446..7115b9265b53f 100644 --- a/plugins/webservices/joomlaupdate/services/provider.php +++ b/plugins/webservices/joomlaupdate/services/provider.php @@ -26,7 +26,7 @@ * * @return void * - * @since 4.4.0 + * @since __DEPLOY_VERSION__ */ public function register(Container $container): void { diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index e220bb26bb0b7..e1f936364cfa8 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -47,7 +47,7 @@ public static function getSubscribedEvents(): array * * @return void * - * @since 4.0.0 + * @since __DEPLOY_VERSION__ */ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void { From 5842280d0134d7f49218ce17d8e5303ae3df8e2f Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 14:18:51 +0100 Subject: [PATCH 011/130] Add joomlaupdate webservice plugin as core extension --- libraries/src/Extension/ExtensionHelper.php | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/src/Extension/ExtensionHelper.php b/libraries/src/Extension/ExtensionHelper.php index f17b506296849..c1d717b9d8959 100644 --- a/libraries/src/Extension/ExtensionHelper.php +++ b/libraries/src/Extension/ExtensionHelper.php @@ -338,6 +338,7 @@ class ExtensionHelper ['plugin', 'contact', 'webservices', 0], ['plugin', 'content', 'webservices', 0], ['plugin', 'installer', 'webservices', 0], + ['plugin', 'joomlaupdate', 'webservices', 0], ['plugin', 'languages', 'webservices', 0], ['plugin', 'media', 'webservices', 0], ['plugin', 'menus', 'webservices', 0], From 24c7e06a7c6e55dc37f91142a3a009d84774c032 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 14:28:20 +0100 Subject: [PATCH 012/130] Add missing comment --- .../src/Controller/HealthcheckController.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index b8e286f74e4e1..5db5d5eee55d7 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -42,6 +42,13 @@ class HealthcheckController extends ApiController */ protected $default_view = 'healthcheck'; + /** + * Show the healthcheck information + * + * @return HealthcheckController + * + * @since __DEPLOY_VERSION__ + */ public function show() { $this->validateUpdateToken(); From e0685ec07bf3cffbcd0c480493b023f85773255e Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 14:37:53 +0100 Subject: [PATCH 013/130] Fix comment --- .../com_joomlaupdate/src/Extension/JoomlaupdateComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php index 5a538e950b070..9273461b65304 100644 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -53,7 +53,7 @@ public function prepareForm(Form $form, $data) : void { $form->removeField('update_token'); } - // If we want automated updates, check if we have an old key to use otherwise generate a new one (don't use the submited one, if could be manipulated) + // If we want automated updates, check if we have an old key to use otherwise generate a new one else { $config = ComponentHelper::getParams('com_joomlaupdate'); From 63dc17ee707706b2bd535a6e2cdb26cfcc00ac39 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 16 Nov 2024 16:15:25 +0100 Subject: [PATCH 014/130] Add type hint for model --- .../com_joomlaupdate/src/Controller/HealthcheckController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index 5db5d5eee55d7..84d6236700395 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -13,6 +13,7 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\ApiController; +use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; use Tobscure\JsonApi\Exception\InvalidParameterException; // phpcs:disable PSR1.Files.SideEffects @@ -71,7 +72,7 @@ public function show() $modelName = $this->input->get('model', $this->contentType); - /** @var ListModel $model */ + /** @var UpdateModel $model */ $model = $this->getModel('Update', 'Administrator', ['ignore_request' => true, 'state' => $this->modelState]); if (!$model) { From c3fca3eebe89952317f203f13fbe3860e299e3d1 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 10:07:38 +0100 Subject: [PATCH 015/130] Return error in health check when auto update is disabled --- .../src/Controller/HealthcheckController.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index 84d6236700395..69855dd66f47e 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -166,14 +166,19 @@ protected function allowAdd($data = []) } protected function validateUpdateToken() : void { + + $config = ComponentHelper::getParams('com_joomlaupdate'); + + if (!in_array($config->get('autoupdate', 'none'), ['patch', 'minor'])) { + throw new \RuntimeException('Auto update is disabled', 404); + } + $token = $this->input->server->get('HTTP_X_JUPDATE_TOKEN', '', 'STRING'); if (empty($token)) { throw new InvalidParameterException('Token is required', 403, null, 'token'); } - $config = ComponentHelper::getParams('com_joomlaupdate'); - if ($config->get('update_token') !== $token) { throw new InvalidParameterException('Invalid token', 403, null, 'token'); } From 4674f23443da07cd40e0ad8a50c9c178ee5880ed Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 10:31:13 +0100 Subject: [PATCH 016/130] Move primary method to top in health check --- .../src/View/Healthcheck/JsonapiView.php | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php index 0b9bd8e298484..82142ff884744 100644 --- a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php @@ -27,6 +27,25 @@ */ class JsonapiView extends BaseApiView { + /** + * Generates the health check output + * + * @return string The rendered data + * + * @since __DEPLOY_VERSION__ + */ + public function healthCheck() { + $data = $this->getStatsData(); + + $element = (new Resource($data, $this->serializer)) + ->fields(['healthcheck' => ['php_version', 'db_type', 'db_version', 'cms_version', 'server_os']]); + + $this->getDocument()->setData($element); + $this->getDocument()->addLink('self', Uri::current()); + + return $this->getDocument()->render(); + } + /** * Get the data that will be sent to the update server. * @@ -53,21 +72,4 @@ protected function getStatsData() return $data; } - - /** - * Generates the health check output - * - * @return void - */ - public function healthCheck() { - $data = $this->getStatsData(); - - $element = (new Resource($data, $this->serializer)) - ->fields(['healthcheck' => ['php_version', 'db_type', 'db_version', 'cms_version', 'server_os']]); - - $this->getDocument()->setData($element); - $this->getDocument()->addLink('self', Uri::current()); - - return $this->getDocument()->render(); - } } From c782085e00a3711fdcaa8786db8e8274022805f0 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 10:34:29 +0100 Subject: [PATCH 017/130] Implement getUpdate webservice call --- .../src/Model/UpdateModel.php | 39 ++++ .../src/Controller/UpdatesController.php | 182 ++++++++++++++++++ .../src/View/Updates/JsonapiView.php | 84 ++++++++ libraries/src/Updater/ConstraintChecker.php | 22 ++- libraries/src/Updater/Updater.php | 31 +++ .../src/Extension/Joomlaupdate.php | 1 + 6 files changed, 357 insertions(+), 2 deletions(-) create mode 100644 api/components/com_joomlaupdate/src/Controller/UpdatesController.php create mode 100644 api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index 0896c0cc414c4..ff938aac4188b 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -1031,6 +1031,45 @@ public function upload() Factory::getApplication()->setUserState('com_joomlaupdate.temp_file', $tmp_dest); } + /** + * Get a specific update based on the configuration of Joomla + * + * @return string|null The version of the available update or null if not found + */ + public function getAvailableAutoUpdates() : ?string + { + $params = ComponentHelper::getParams('com_joomlaupdate'); + + $updater = Updater::getInstance(); + + // Here be dragons, crazy stuff to overcome some Joomla! restrictions + + // For automated updates, we stay in the current major version, so make sure we don't look for "next" + // @todo remove this restriction to also update to the next major version + // We also check if we want only patch level updates + switch ($params->get('autoupdate')) { + case 'patch': + $params->set('patchOnly', true); + case 'minor': + case 'major': + default: + $params->set('updatesource', 'default'); + break; + } + + $updates = $updater->getAvailableUpdates(ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id, Updater::STABILITY_STABLE); + + $latestVersion = null; + + foreach ($updates as $update) { + if (!$latestVersion || version_compare($update['version'], $latestVersion) > 0) { + $latestVersion = $update['version']; + } + } + + return $latestVersion; + } + /** * Checks the super admin credentials are valid for the currently logged in users * diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php new file mode 100644 index 0000000000000..4c3d66d36f5f2 --- /dev/null +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -0,0 +1,182 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Api\Controller; + +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\Controller\ApiController; +use Tobscure\JsonApi\Exception\InvalidParameterException; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * The healthcheck controller + * + * @since __DEPLOY_VERSION__ + */ +class UpdatesController extends ApiController +{ + /** + * The content type of the item. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $contentType = 'updates'; + + /** + * The default view for the display method. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $default_view = 'updates'; + + public function getUpdate() { + $this->validateUpdateToken(); + + $this->displayOutput('getUpdate'); + } + + /** + * Generic method to call the different views + * + * @param [type] $method + * @return void + */ + protected function displayOutput($method) { + + $viewType = $this->app->getDocument()->getType(); + $viewName = $this->input->get('view', $this->default_view); + $viewLayout = $this->input->get('layout', 'default', 'string'); + + try { + /** @var JsonApiView $view */ + $view = $this->getView( + $viewName, + $viewType, + '', + ['base_path' => $this->basePath, 'layout' => $viewLayout, 'contentType' => $this->contentType] + ); + } catch (\Exception $e) { + throw new \RuntimeException($e->getMessage()); + } + + $modelName = $this->input->get('model', $this->contentType); + + /** @var UpdateModel $model */ + $model = $this->getModel('Update', 'Administrator', ['ignore_request' => true, 'state' => $this->modelState]); + + if (!$model) { + throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_MODEL_CREATE')); + } + + // Push the model into the view (as default) + $view->setModel($model, true); + + $view->setDocument($this->app->getDocument()); + + $view->$method(); + } + + /** + * Basic display of an item view. We don't allow this + * + * @param integer $id The primary key to display. Leave empty if you want to retrieve data from the request + * + * @return static A \JControllerLegacy object to support chaining. + * + * @since __DEPLOY_VERSION__ + */ + public function displayItem($id = null) + { + throw new \RuntimeException('Not implemented', 501); + } + + /** + * List view amended to add filtering of data. We don't allow this + * + * @return static A BaseController object to support chaining. + * + * @since __DEPLOY_VERSION__ + */ + public function displayList() + { + throw new \RuntimeException('Not implemented', 501); + } + + /** + * Removes an item. + * + * @param integer $id The primary key to delete item. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function delete($id = null) + { + throw new \RuntimeException('Not implemented', 501); + } + + /** + * Method to check if you can edit an existing record. + * + * We don't allow editing from API (yet?) + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key; default is id. + * + * @return boolean + * + * @since __DEPLOY_VERSION__ + */ + protected function allowEdit($data = [], $key = 'id') + { + return false; + } + + /** + * Method to check if you can add a new record. + * + * We don't allow adding from API + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since __DEPLOY_VERSION__ + */ + protected function allowAdd($data = []) + { + return false; + } + + protected function validateUpdateToken() : void { + $config = ComponentHelper::getParams('com_joomlaupdate'); + + if (!in_array($config->get('autoupdate', 'none'), ['patch', 'minor'])) { + throw new \RuntimeException('Auto update is disabled', 404); + } + + $token = $this->input->server->get('HTTP_X_JUPDATE_TOKEN', '', 'STRING'); + + if (empty($token)) { + throw new InvalidParameterException('Token is required', 403, null, 'token'); + } + + if ($config->get('update_token') !== $token) { + throw new InvalidParameterException('Invalid token', 403, null, 'token'); + } + } +} diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php new file mode 100644 index 0000000000000..f5abad47b895e --- /dev/null +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -0,0 +1,84 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Api\View\Updates; + +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Extension\ExtensionHelper; +use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; +use Joomla\CMS\Updater\Updater; +use Joomla\CMS\Uri\Uri; +use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; +use Tobscure\JsonApi\Resource; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * The healthcheck view + * + * @since __DEPLOY_VERSION__ + */ +class JsonapiView extends BaseApiView +{ + /** + * Generates the health check output + * + * @return string The rendered data + * + * @since __DEPLOY_VERSION__ + */ + public function getUpdate() { + $params = ComponentHelper::getParams('com_joomlaupdate'); + + $updater = Updater::getInstance(); + + // Here be dragons, crazy stuff to overcome some Joomla! restrictions + + // For automated updates, we stay in the current major version, so make sure we don't look for "next" + // @todo remove this restriction to also update to the next major version + // We also check if we want only patch level updates + switch ($params->get('autoupdate')) { + case 'patch': + $params->set('patchOnly', true); + case 'minor': + case 'major': + default: + $params->set('updatesource', 'default'); + break; + } + + $updates = $updater->getAvailableUpdates(ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id, Updater::STABILITY_STABLE); + + $latestVersion = null; + + foreach ($updates as $update) { + if (!$latestVersion || version_compare($update['version'], $latestVersion) > 0) { + $latestVersion = $update['version']; + } + } + + /** + * @var UpdateModel $model + */ + $model = $this->getModel(); + + $latestVersion = $model->getAvailableAutoUpdates(); + + $element = (new Resource(['availableUpdate' => $latestVersion], $this->serializer)) + ->fields(['checkUpdate' => ['availableUpdate']]); + + $this->getDocument()->setData($element); + $this->getDocument()->addLink('self', Uri::current()); + + return $this->getDocument()->render(); + } +} diff --git a/libraries/src/Updater/ConstraintChecker.php b/libraries/src/Updater/ConstraintChecker.php index c6952265f2312..26a38445a882e 100644 --- a/libraries/src/Updater/ConstraintChecker.php +++ b/libraries/src/Updater/ConstraintChecker.php @@ -44,6 +44,13 @@ class ConstraintChecker */ protected $channel; + /** + * True if we should stay in the patch release + * + * @var boolean + */ + protected $patchOnly = false; + /** * Constructor, used to populate the failed * @@ -57,12 +64,17 @@ public function __construct($channel = null) { $this->failedEnvironmentConstraints = new \stdClass(); - if (!isset($channel)) { - $params = ComponentHelper::getParams('com_joomlaupdate'); + $params = ComponentHelper::getParams('com_joomlaupdate'); + if (!isset($channel)) { $channel = (Version::MAJOR_VERSION + ($params->get('updatesource', 'default') == 'next' ? 1 : 0)) . '.x'; } + // We should stay in the patch release + if ($params->get('patchOnly')) { + $this->patchOnly = true; + } + $this->channel = $channel; } @@ -101,6 +113,12 @@ public function check(array $candidate, $minimumStability = Updater::STABILITY_S return false; } + list($major, $minor) = explode('.', $candidate['version']); + + if ($this->patchOnly && version_compare(Version::MAJOR_VERSION . '.' . Version::MINOR_VERSION, $major . '.' . $minor) !== 0) { + return false; + } + $result = true; // Check php_minimum, assume true when not set diff --git a/libraries/src/Updater/Updater.php b/libraries/src/Updater/Updater.php index a46a8309448e1..1686aaa6dcee6 100644 --- a/libraries/src/Updater/Updater.php +++ b/libraries/src/Updater/Updater.php @@ -180,6 +180,37 @@ public function findUpdates($eid = 0, $cacheTimeout = 0, $minimumStability = sel return $retval; } + /** + * Returns available updates + * + * @param integer $eid + * @param string $minimumStability + * @param boolean $includeCurrent + * + * @return array + */ + public function getAvailableUpdates(int $eid, string $minimumStability = self::STABILITY_STABLE) : array + { + $results = $this->getUpdateSites($eid); + + if (empty($results)) { + return []; + } + + $updateObjects = []; + + foreach ($results as $result) { + + $updateElements = $this->getUpdateObjectsForSite($result, $minimumStability); + + foreach ($updateElements as $updateElement) { + $updateObjects[] = get_object_vars($updateElement); + } + } + + return $updateObjects; + } + /** * Returns the update site records for an extension with ID $eid. If $eid is zero all enabled update sites records * will be returned. diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index e1f936364cfa8..8e982050e4e26 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -57,6 +57,7 @@ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void $routes = [ new Route(['GET'], 'v1/joomlaupdate/healthcheck', 'healthcheck.show', [], $defaults), + new Route(['GET'], 'v1/joomlaupdate/getUpdate', 'updates.getUpdate', [], $defaults), ]; $router->addRoutes($routes); From 2a351f934f79b77d43782a876f92cda6722b7171 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 10:43:54 +0100 Subject: [PATCH 018/130] Make view call more generic --- .../src/Controller/UpdatesController.php | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php index 4c3d66d36f5f2..921e61f100651 100644 --- a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -13,6 +13,7 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\ApiController; +use Joomla\Component\Joomlaupdate\Api\View\Updates\JsonapiView; use Tobscure\JsonApi\Exception\InvalidParameterException; // phpcs:disable PSR1.Files.SideEffects @@ -37,24 +38,32 @@ class UpdatesController extends ApiController /** * The default view for the display method. * - * @var string + * @var string * @since __DEPLOY_VERSION__ */ protected $default_view = 'updates'; + /** + * Get the latest update version for the auto updater + * + * @return UpdateController Self for chaining + */ public function getUpdate() { $this->validateUpdateToken(); - $this->displayOutput('getUpdate'); + $view = $this->prepareView(); + + $view->getUpdate(); + + return $this; } /** - * Generic method to call the different views + * Generic method to prepare the view * - * @param [type] $method - * @return void + * @return JsonapiView The prepared view */ - protected function displayOutput($method) { + protected function prepareView() { $viewType = $this->app->getDocument()->getType(); $viewName = $this->input->get('view', $this->default_view); @@ -86,7 +95,7 @@ protected function displayOutput($method) { $view->setDocument($this->app->getDocument()); - $view->$method(); + return $view; } /** From 59786d3dd36e87ef5b88d23d2d0bc7c4ea26a98c Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 10:49:29 +0100 Subject: [PATCH 019/130] Remove unused code --- .../src/View/Updates/JsonapiView.php | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index f5abad47b895e..07192a570aa8b 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -39,33 +39,6 @@ class JsonapiView extends BaseApiView public function getUpdate() { $params = ComponentHelper::getParams('com_joomlaupdate'); - $updater = Updater::getInstance(); - - // Here be dragons, crazy stuff to overcome some Joomla! restrictions - - // For automated updates, we stay in the current major version, so make sure we don't look for "next" - // @todo remove this restriction to also update to the next major version - // We also check if we want only patch level updates - switch ($params->get('autoupdate')) { - case 'patch': - $params->set('patchOnly', true); - case 'minor': - case 'major': - default: - $params->set('updatesource', 'default'); - break; - } - - $updates = $updater->getAvailableUpdates(ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id, Updater::STABILITY_STABLE); - - $latestVersion = null; - - foreach ($updates as $update) { - if (!$latestVersion || version_compare($update['version'], $latestVersion) > 0) { - $latestVersion = $update['version']; - } - } - /** * @var UpdateModel $model */ From 3183cfacc03fa30e398f2c0d247c905d0daa289a Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 10:51:33 +0100 Subject: [PATCH 020/130] Rename parameter --- .../com_joomlaupdate/src/View/Updates/JsonapiView.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index 07192a570aa8b..11f74a73d3f92 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -47,7 +47,7 @@ public function getUpdate() { $latestVersion = $model->getAvailableAutoUpdates(); $element = (new Resource(['availableUpdate' => $latestVersion], $this->serializer)) - ->fields(['checkUpdate' => ['availableUpdate']]); + ->fields(['getUpdate' => ['availableUpdate']]); $this->getDocument()->setData($element); $this->getDocument()->addLink('self', Uri::current()); From b3366c43ed5b96b88e4462e3bb2d913754e0102f Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 12:09:59 +0100 Subject: [PATCH 021/130] Update joomlaupdate config --- .../components/com_joomlaupdate/config.xml | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index dc64cdc0defb5..c99af288b1112 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -75,27 +75,28 @@
- - - + + + +
From 4810a62300851105856d836b49cce911deb4b0ed Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 12:15:14 +0100 Subject: [PATCH 022/130] Reimplement token generation --- .../src/Extension/JoomlaupdateComponent.php | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php index 9273461b65304..da182eccdf8d1 100644 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -48,25 +48,20 @@ public function prepareForm(Form $form, $data) : void return; } - // We remove the token field, if no auto update is selected - if (empty($data['autoupdate']) || !in_array($data['autoupdate'], ['minor', 'patch'])) - { - $form->removeField('update_token'); - } // If we want automated updates, check if we have an old key to use otherwise generate a new one - else { - $config = ComponentHelper::getParams('com_joomlaupdate'); + $config = ComponentHelper::getParams('com_joomlaupdate'); - $token = $config->get('update_token'); + $token = $config->get('update_token'); - if (empty($token)) - { - $token = UserHelper::genRandomPassword(40); - } - - $form->setFieldAttribute('update_token', 'default', $token); + if (empty($token)) + { + $token = UserHelper::genRandomPassword(40); } + $form->setFieldAttribute('update_token', 'default', $token); + + $data['update_token'] = $token; + // Handle automated updates when form is submitted (but before it's saved) $input = Factory::getApplication()->getInput(); @@ -84,21 +79,17 @@ public function prepareForm(Form $form, $data) : void * @return void */ protected function manageAutoUpdate($data) { - if (empty($data['autoupdate']) || !in_array($data['autoupdate'], ['minor', 'patch'])) + if (empty($data['autoupdate']) || $data['updatesource'] !== 'default') { - $config = ComponentHelper::getParams('com_joomlaupdate'); - - $token = $config->get('update_token'); - - if ($token) { + if (!empty($data['update_token'])) { // @todo implement - // $this->autoUpdateUnsubscribe($token); + // $this->autoUpdateUnsubscribe($data['update_token']); } return; } // @todo implement - // $this->autoUpdateSubscribe($data); + // $this->autoUpdateSubscribe($data['update_token']); } } From dd3374e9fffc97de2c3c1e3680c5cf632b80cbd2 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 12:30:02 +0100 Subject: [PATCH 023/130] Take care of minimum stability --- administrator/components/com_joomlaupdate/config.xml | 8 ++++---- .../src/Extension/JoomlaupdateComponent.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index c99af288b1112..149401eb167ee 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -83,7 +83,7 @@ description="COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_DESC" default="1" layout="joomla.form.field.radio.switcher" - showon="updatesource:default" + showon="updatesource:default[AND]minimum_stability:4" validate="options" > @@ -96,7 +96,7 @@ label="COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_LABEL" description="COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_DESC" readonly="true" - showon="updatesource:default[AND]autoupdate:1" + showon="updatesource:default[AND]minimum_stability:4[AND]autoupdate:1" /> diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php index da182eccdf8d1..a1127927ba48d 100644 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -79,7 +79,7 @@ public function prepareForm(Form $form, $data) : void * @return void */ protected function manageAutoUpdate($data) { - if (empty($data['autoupdate']) || $data['updatesource'] !== 'default') + if (empty($data['autoupdate']) || $data['updatesource'] !== 'default' || $data['minimum_stability'] !== 'stable') { { if (!empty($data['update_token'])) { // @todo implement From 15079a2fcec5bee6f7d9c8f0acddc2dd46cc6e25 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 12:34:07 +0100 Subject: [PATCH 024/130] Add restricter rule when auto updater is disabled --- .../com_joomlaupdate/src/Controller/HealthcheckController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index 69855dd66f47e..84209bed98369 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -169,7 +169,7 @@ protected function validateUpdateToken() : void { $config = ComponentHelper::getParams('com_joomlaupdate'); - if (!in_array($config->get('autoupdate', 'none'), ['patch', 'minor'])) { + if ($config->get('updatesource') !== 'default' || (int) $config->get('minimum_stability') !== 4 || !$config->get('autoupdate')) { throw new \RuntimeException('Auto update is disabled', 404); } From b14e52ea6ce9ca59e907c7c8b7917973ead1fdae Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 12:41:33 +0100 Subject: [PATCH 025/130] Fix yntax error --- .../com_joomlaupdate/src/Extension/JoomlaupdateComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php index a1127927ba48d..a4d3f62a5c4f9 100644 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -79,7 +79,7 @@ public function prepareForm(Form $form, $data) : void * @return void */ protected function manageAutoUpdate($data) { - if (empty($data['autoupdate']) || $data['updatesource'] !== 'default' || $data['minimum_stability'] !== 'stable') { + if (empty($data['autoupdate']) || $data['updatesource'] !== 'default' || $data['minimum_stability'] !== 'stable') { if (!empty($data['update_token'])) { // @todo implement From 3c546840ffb07220fd0180359b5c77314fd635f1 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 12:52:42 +0100 Subject: [PATCH 026/130] Update getUpdate to use core functionality --- .../com_joomlaupdate/src/Model/UpdateModel.php | 16 ++++++++++++++++ .../src/View/Updates/JsonapiView.php | 10 +++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index ff938aac4188b..c5151a8e8e03d 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -480,6 +480,22 @@ public function updateLastHealthCheck() { $extension->store(); } + /** + * Get the latest version for the auto update + * + * @return string|null + */ + public function getAutoUpdateVersion() : ?string + { + $this->refreshUpdates(true); + + $updateInfo = $this->getUpdateInformation(); + + return $updateInfo['latest'] ?? null; + + print_r($updateInfo);exit; + } + /** * Return the result of the checksum of a package with the SHA256/SHA384/SHA512 tags in the update server manifest * diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index 11f74a73d3f92..531d90717de1d 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -23,14 +23,14 @@ // phpcs:enable PSR1.Files.SideEffects /** - * The healthcheck view + * The updates view * * @since __DEPLOY_VERSION__ */ class JsonapiView extends BaseApiView { /** - * Generates the health check output + * Generates the update output * * @return string The rendered data * @@ -44,7 +44,11 @@ public function getUpdate() { */ $model = $this->getModel(); - $latestVersion = $model->getAvailableAutoUpdates(); + $latestVersion = $model->getAutoUpdateVersion(); + + if (!$latestVersion || version_compare(JVERSION, $latestVersion) >= 0) { + $latestVersion = null; + } $element = (new Resource(['availableUpdate' => $latestVersion], $this->serializer)) ->fields(['getUpdate' => ['availableUpdate']]); From 3755e784b20afa5bdbb8c55e53d433ed264b559e Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 12:53:12 +0100 Subject: [PATCH 027/130] Improve update disable information --- administrator/language/en-GB/com_joomlaupdate.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 7d9d31651ec27..1ebf997c73e62 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -5,7 +5,7 @@ COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." -COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_DESC="Define which releases you want automated updates for. Note: Automated updates are only available for minor and patch releases." +COM_JOOMLAUPDATE_CONFIG_AUTO_UPDATE_DISABLED_LABEL=" Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_LABEL="Automated updates" COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_DESC="Automatically update Joomla to the latest version when it is available." COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_LABEL="Automated Update" From 83d77b2539d8353518b38e2d126c703420fe4ddb Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 13:31:18 +0100 Subject: [PATCH 028/130] Fix notice --- .../com_joomlaupdate/src/View/Updates/JsonapiView.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index 531d90717de1d..fc149749a90a4 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -50,7 +50,7 @@ public function getUpdate() { $latestVersion = null; } - $element = (new Resource(['availableUpdate' => $latestVersion], $this->serializer)) + $element = (new Resource((object) ['id' => 'getUpdate', 'availableUpdate' => $latestVersion], $this->serializer)) ->fields(['getUpdate' => ['availableUpdate']]); $this->getDocument()->setData($element); From 2de0b41a3e2f6707f2a061f20f611047c3773773 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 13:33:39 +0100 Subject: [PATCH 029/130] Fix notice --- .../com_joomlaupdate/src/View/Healthcheck/JsonapiView.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php index 82142ff884744..ba66421a93334 100644 --- a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php @@ -37,7 +37,9 @@ class JsonapiView extends BaseApiView public function healthCheck() { $data = $this->getStatsData(); - $element = (new Resource($data, $this->serializer)) + $data['id'] = 'healthcheck'; + + $element = (new Resource((object) $data, $this->serializer)) ->fields(['healthcheck' => ['php_version', 'db_type', 'db_version', 'cms_version', 'server_os']]); $this->getDocument()->setData($element); From b25bba3bf60c27b62dfbedf2ebaba01150d31160 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 13:38:54 +0100 Subject: [PATCH 030/130] Correct ID --- .../com_joomlaupdate/src/View/Updates/JsonapiView.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index fc149749a90a4..c3c76400578b2 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -50,8 +50,8 @@ public function getUpdate() { $latestVersion = null; } - $element = (new Resource((object) ['id' => 'getUpdate', 'availableUpdate' => $latestVersion], $this->serializer)) - ->fields(['getUpdate' => ['availableUpdate']]); + $element = (new Resource((object) ['availableUpdate' => $latestVersion, 'id' => 'getUpdate'], $this->serializer)) + ->fields(['updates' => ['availableUpdate']]); $this->getDocument()->setData($element); $this->getDocument()->addLink('self', Uri::current()); From e7f993859a9d83183d4a6154260f70bb7552d676 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 13:50:23 +0100 Subject: [PATCH 031/130] Add prepareUpdate --- .../src/Model/UpdateModel.php | 73 ++++++++----------- .../language/en-GB/com_joomlaupdate.ini | 3 - .../src/Controller/UpdatesController.php | 38 +++++++++- .../src/View/Updates/JsonapiView.php | 31 +++++++- .../src/Extension/Joomlaupdate.php | 1 + 5 files changed, 97 insertions(+), 49 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index c5151a8e8e03d..a0e3aafffc905 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -465,7 +465,8 @@ public function download() * * @since __DEPLOY_VERSION__ */ - public function updateLastHealthCheck() { + public function updateLastHealthCheck() + { $extension = new Extension($this->getDatabase()); $extensionId = $extension->find(['element' => 'com_joomlaupdate']); @@ -492,8 +493,37 @@ public function getAutoUpdateVersion() : ?string $updateInfo = $this->getUpdateInformation(); return $updateInfo['latest'] ?? null; + } + + /** + * Download file and request password/filesize information + * + * @param string $targetVersion + * + * @return array + */ + public function prepareAutoUpdate(string $targetVersion) : array + { + $fileInformation = $this->download(); + + if ($fileInformation['version'] !== $targetVersion) { + throw new \Exception(Text::_('COM_JOOMLAUPDATE_VIEW_UPDATE_VERSION_WRONG'), 410); + } + + if ($fileInformation['check'] === false) { + throw new \Exception(Text::_('COM_JOOMLAUPDATE_VIEW_UPDATE_CHECKSUM_WRONG'), 410); + } + + if (!$this->createUpdateFile($fileInformation['basename'])) { + throw new \Exception('Could not write update file', 410); + } - print_r($updateInfo);exit; + $app = Factory::getApplication(); + + return [ + 'password' => $app->getUserState('com_joomlaupdate.password'), + 'filesize' => $app->getUserState('com_joomlaupdate.filesize'), + ]; } /** @@ -1047,45 +1077,6 @@ public function upload() Factory::getApplication()->setUserState('com_joomlaupdate.temp_file', $tmp_dest); } - /** - * Get a specific update based on the configuration of Joomla - * - * @return string|null The version of the available update or null if not found - */ - public function getAvailableAutoUpdates() : ?string - { - $params = ComponentHelper::getParams('com_joomlaupdate'); - - $updater = Updater::getInstance(); - - // Here be dragons, crazy stuff to overcome some Joomla! restrictions - - // For automated updates, we stay in the current major version, so make sure we don't look for "next" - // @todo remove this restriction to also update to the next major version - // We also check if we want only patch level updates - switch ($params->get('autoupdate')) { - case 'patch': - $params->set('patchOnly', true); - case 'minor': - case 'major': - default: - $params->set('updatesource', 'default'); - break; - } - - $updates = $updater->getAvailableUpdates(ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id, Updater::STABILITY_STABLE); - - $latestVersion = null; - - foreach ($updates as $update) { - if (!$latestVersion || version_compare($update['version'], $latestVersion) > 0) { - $latestVersion = $update['version']; - } - } - - return $latestVersion; - } - /** * Checks the super admin credentials are valid for the currently logged in users * diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 1ebf997c73e62..b807f02fd57b6 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -9,9 +9,6 @@ COM_JOOMLAUPDATE_CONFIG_AUTO_UPDATE_DISABLED_LABEL="validateUpdateToken(); $view = $this->prepareView(); @@ -58,6 +59,37 @@ public function getUpdate() { return $this; } + /** + * Prepare the update and output the update information + * + * @return UpdatesController + * + * @since __DEPLOY_VERSION__ + */ + public function prepareUpdate() + { + $this->validateUpdateToken(); + + /** + * @var UpdateModel $model + */ + $model = $this->getModel('Update'); + + $latestVersion = $model->getAutoUpdateVersion(); + + $targetVersion = $this->input->getString('targetVersion'); + + if (!$latestVersion || $latestVersion !== $targetVersion) { + throw new \Exception(Text::_('COM_JOOMLAUPDATE_VIEW_UPDATE_VERSION_WRONG'), 410); + } + + $view = $this->prepareView(); + + $view->prepareUpdate($targetVersion); + + return $this; + } + /** * Generic method to prepare the view * @@ -174,7 +206,7 @@ protected function allowAdd($data = []) protected function validateUpdateToken() : void { $config = ComponentHelper::getParams('com_joomlaupdate'); - if (!in_array($config->get('autoupdate', 'none'), ['patch', 'minor'])) { + if ($config->get('updatesource') !== 'default' || (int) $config->get('minimum_stability') !== 4 || !$config->get('autoupdate')) { throw new \RuntimeException('Auto update is disabled', 404); } diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index c3c76400578b2..bc71c51396c78 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -11,9 +11,7 @@ namespace Joomla\Component\Joomlaupdate\Api\View\Updates; use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Extension\ExtensionHelper; use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; -use Joomla\CMS\Updater\Updater; use Joomla\CMS\Uri\Uri; use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; use Tobscure\JsonApi\Resource; @@ -58,4 +56,33 @@ public function getUpdate() { return $this->getDocument()->render(); } + + /** + * Prepares the update by setting up the update.php and returns password and file size + * + * @param string $targetVersion The target version to prepare + * + * @return string The rendered data + * + * @since __DEPLOY_VERSION__ + */ + public function prepareUpdate(string $targetVersion) : string + { + /** + * @var UpdateModel $model + */ + $model = $this->getModel(); + + $fileinformation = $model->prepareAutoUpdate($targetVersion); + + $fileinformation['id'] = 'prepareUpdate'; + + $element = (new Resource((object) $fileinformation, $this->serializer)) + ->fields(['updates' => ['password', 'filesize']]); + + $this->getDocument()->setData($element); + $this->getDocument()->addLink('self', Uri::current()); + + return $this->getDocument()->render(); + } } diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index 8e982050e4e26..6e11fad520adc 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -58,6 +58,7 @@ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void $routes = [ new Route(['GET'], 'v1/joomlaupdate/healthcheck', 'healthcheck.show', [], $defaults), new Route(['GET'], 'v1/joomlaupdate/getUpdate', 'updates.getUpdate', [], $defaults), + new Route(['GET'], 'v1/joomlaupdate/prepareUpdate', 'updates.prepareUpdate', [], $defaults), ]; $router->addRoutes($routes); From 427c9b310237fef0257469988bbc8f2ccdfa901e Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 13:59:27 +0100 Subject: [PATCH 032/130] Add update finalization --- .../src/Controller/UpdatesController.php | 16 ++++++++++ .../src/View/Updates/JsonapiView.php | 30 +++++++++++++++++++ .../src/Extension/Joomlaupdate.php | 1 + 3 files changed, 47 insertions(+) diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php index 86d66b93bdf93..68cdbb3e1821b 100644 --- a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -90,6 +90,22 @@ public function prepareUpdate() return $this; } + /** + * Finalize the update + * + * @return UpdateController For chaining + */ + public function finalizeUpdate() + { + $this->validateUpdateToken(); + + $view = $this->prepareView(); + + $view->finalizeUpdate(); + + return $this; + } + /** * Generic method to prepare the view * diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index bc71c51396c78..bd8add264daf7 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -85,4 +85,34 @@ public function prepareUpdate(string $targetVersion) : string return $this->getDocument()->render(); } + + public function finalizeUpdate() + { + /** + * @var UpdateModel $model + */ + $model = $this->getModel(); + + try { + $model->finaliseUpgrade(); + } catch (\Throwable $e) { + $model->collectError('finaliseUpgrade', $e); + } + + $model->resetUpdateSource(); + + $success = true; + + if ($model->getErrors()) { + $success = false; + } + + $element = (new Resource((object) ['success' => $success, 'id' => 'finalizeUpdate'], $this->serializer)) + ->fields(['updates' => ['success']]); + + $this->getDocument()->setData($element); + $this->getDocument()->addLink('self', Uri::current()); + + return $this->getDocument()->render(); + } } diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index 6e11fad520adc..2b26ac411ed54 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -59,6 +59,7 @@ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void new Route(['GET'], 'v1/joomlaupdate/healthcheck', 'healthcheck.show', [], $defaults), new Route(['GET'], 'v1/joomlaupdate/getUpdate', 'updates.getUpdate', [], $defaults), new Route(['GET'], 'v1/joomlaupdate/prepareUpdate', 'updates.prepareUpdate', [], $defaults), + new Route(['GET'], 'v1/joomlaupdate/finalizeUpdate', 'updates.finalizeUpdate', [], $defaults), ]; $router->addRoutes($routes); From 81158e42fb6c7553be36c1bef056768fb0a96ef7 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 14:34:35 +0100 Subject: [PATCH 033/130] Convert prepareUpdate and finalizeUpdate to POST --- .../webservices/joomlaupdate/src/Extension/Joomlaupdate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index 2b26ac411ed54..137089abdcefb 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -58,8 +58,8 @@ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void $routes = [ new Route(['GET'], 'v1/joomlaupdate/healthcheck', 'healthcheck.show', [], $defaults), new Route(['GET'], 'v1/joomlaupdate/getUpdate', 'updates.getUpdate', [], $defaults), - new Route(['GET'], 'v1/joomlaupdate/prepareUpdate', 'updates.prepareUpdate', [], $defaults), - new Route(['GET'], 'v1/joomlaupdate/finalizeUpdate', 'updates.finalizeUpdate', [], $defaults), + new Route(['POST'], 'v1/joomlaupdate/prepareUpdate', 'updates.prepareUpdate', [], $defaults), + new Route(['POST'], 'v1/joomlaupdate/finalizeUpdate', 'updates.finalizeUpdate', [], $defaults), ]; $router->addRoutes($routes); From a3f4f18b77bf11205600c39ff7b1694ee87e88d1 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 14:46:34 +0100 Subject: [PATCH 034/130] Fix code style --- .../src/Extension/JoomlaupdateComponent.php | 17 +++++++---------- .../com_joomlaupdate/src/Model/UpdateModel.php | 4 ++-- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php index a4d3f62a5c4f9..9832c486a3ee7 100644 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -41,10 +41,9 @@ class JoomlaupdateComponent extends MVCComponent implements ConfigServiceInterfa * * @since __DEPLOY_VERSION__ */ - public function prepareForm(Form $form, $data) : void + public function prepareForm(Form $form, $data): void { - if ($form->getName() !== 'com_config.component') - { + if ($form->getName() !== 'com_config.component') { return; } @@ -53,8 +52,7 @@ public function prepareForm(Form $form, $data) : void $token = $config->get('update_token'); - if (empty($token)) - { + if (empty($token)) { $token = UserHelper::genRandomPassword(40); } @@ -65,8 +63,7 @@ public function prepareForm(Form $form, $data) : void // Handle automated updates when form is submitted (but before it's saved) $input = Factory::getApplication()->getInput(); - if ($input->getMethod() === 'POST') - { + if ($input->getMethod() === 'POST') { $this->manageAutoUpdate($data); } } @@ -78,9 +75,9 @@ public function prepareForm(Form $form, $data) : void * * @return void */ - protected function manageAutoUpdate($data) { - if (empty($data['autoupdate']) || $data['updatesource'] !== 'default' || $data['minimum_stability'] !== 'stable') - { + protected function manageAutoUpdate($data) + { + if (empty($data['autoupdate']) || $data['updatesource'] !== 'default' || $data['minimum_stability'] !== 'stable') { if (!empty($data['update_token'])) { // @todo implement // $this->autoUpdateUnsubscribe($data['update_token']); diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index a0e3aafffc905..31743080a893e 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -486,7 +486,7 @@ public function updateLastHealthCheck() * * @return string|null */ - public function getAutoUpdateVersion() : ?string + public function getAutoUpdateVersion(): ?string { $this->refreshUpdates(true); @@ -502,7 +502,7 @@ public function getAutoUpdateVersion() : ?string * * @return array */ - public function prepareAutoUpdate(string $targetVersion) : array + public function prepareAutoUpdate(string $targetVersion): array { $fileInformation = $this->download(); From 6841fb936a06dc7b55e232fbae12533b97b88fa4 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sun, 17 Nov 2024 14:55:41 +0100 Subject: [PATCH 035/130] Code style fix --- .../com_joomlaupdate/src/Model/UpdateModel.php | 4 ++++ .../src/Controller/HealthcheckController.php | 13 +++++++++++-- .../src/Controller/UpdatesController.php | 15 +++++++++++++-- .../src/View/Healthcheck/JsonapiView.php | 3 ++- .../src/View/Updates/JsonapiView.php | 5 +++-- libraries/src/Config/ConfigServiceInterface.php | 2 +- libraries/src/Config/ConfigServiceTrait.php | 2 +- libraries/src/Updater/Updater.php | 3 +-- 8 files changed, 36 insertions(+), 11 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index 31743080a893e..8a6964f421491 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -485,6 +485,8 @@ public function updateLastHealthCheck() * Get the latest version for the auto update * * @return string|null + * + * @since __DEPLOY_VERSION__ */ public function getAutoUpdateVersion(): ?string { @@ -501,6 +503,8 @@ public function getAutoUpdateVersion(): ?string * @param string $targetVersion * * @return array + * + * @since __DEPLOY_VERSION__ */ public function prepareAutoUpdate(string $targetVersion): array { diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index 84209bed98369..d4cebbcb1578c 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -165,8 +165,17 @@ protected function allowAdd($data = []) return false; } - protected function validateUpdateToken() : void { - + /** + * Validate if the update token is correct and auto update is enabled + * + * @return void + * + * @since __DEPLOY_VERSION__ + * + * @throws Exception + */ + protected function validateUpdateToken(): void + { $config = ComponentHelper::getParams('com_joomlaupdate'); if ($config->get('updatesource') !== 'default' || (int) $config->get('minimum_stability') !== 4 || !$config->get('autoupdate')) { diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php index 68cdbb3e1821b..9252d3cf800e0 100644 --- a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -111,7 +111,8 @@ public function finalizeUpdate() * * @return JsonapiView The prepared view */ - protected function prepareView() { + protected function prepareView() + { $viewType = $this->app->getDocument()->getType(); $viewName = $this->input->get('view', $this->default_view); @@ -219,7 +220,17 @@ protected function allowAdd($data = []) return false; } - protected function validateUpdateToken() : void { + /** + * Validate if the update token is correct and auto update is enabled + * + * @return void + * + * @since __DEPLOY_VERSION__ + * + * @throws Exception + */ + protected function validateUpdateToken(): void + { $config = ComponentHelper::getParams('com_joomlaupdate'); if ($config->get('updatesource') !== 'default' || (int) $config->get('minimum_stability') !== 4 || !$config->get('autoupdate')) { diff --git a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php index ba66421a93334..ef938b1865591 100644 --- a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php @@ -34,7 +34,8 @@ class JsonapiView extends BaseApiView * * @since __DEPLOY_VERSION__ */ - public function healthCheck() { + public function healthCheck() + { $data = $this->getStatsData(); $data['id'] = 'healthcheck'; diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index bd8add264daf7..cf81d01b3f724 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -34,7 +34,8 @@ class JsonapiView extends BaseApiView * * @since __DEPLOY_VERSION__ */ - public function getUpdate() { + public function getUpdate() + { $params = ComponentHelper::getParams('com_joomlaupdate'); /** @@ -66,7 +67,7 @@ public function getUpdate() { * * @since __DEPLOY_VERSION__ */ - public function prepareUpdate(string $targetVersion) : string + public function prepareUpdate(string $targetVersion): string { /** * @var UpdateModel $model diff --git a/libraries/src/Config/ConfigServiceInterface.php b/libraries/src/Config/ConfigServiceInterface.php index 097c32c2b6bde..f688f1df79c53 100644 --- a/libraries/src/Config/ConfigServiceInterface.php +++ b/libraries/src/Config/ConfigServiceInterface.php @@ -30,5 +30,5 @@ interface ConfigServiceInterface * * @return void */ - public function prepareForm(Form $form, $data) : void; + public function prepareForm(Form $form, $data): void; } diff --git a/libraries/src/Config/ConfigServiceTrait.php b/libraries/src/Config/ConfigServiceTrait.php index acdc03c1731d6..8c9685175324e 100644 --- a/libraries/src/Config/ConfigServiceTrait.php +++ b/libraries/src/Config/ConfigServiceTrait.php @@ -30,7 +30,7 @@ trait ConfigServiceTrait * * @return void */ - public function prepareForm(Form $form, $data) : void + public function prepareForm(Form $form, $data): void { } } diff --git a/libraries/src/Updater/Updater.php b/libraries/src/Updater/Updater.php index 1686aaa6dcee6..3ec8d18705c1c 100644 --- a/libraries/src/Updater/Updater.php +++ b/libraries/src/Updater/Updater.php @@ -189,7 +189,7 @@ public function findUpdates($eid = 0, $cacheTimeout = 0, $minimumStability = sel * * @return array */ - public function getAvailableUpdates(int $eid, string $minimumStability = self::STABILITY_STABLE) : array + public function getAvailableUpdates(int $eid, string $minimumStability = self::STABILITY_STABLE): array { $results = $this->getUpdateSites($eid); @@ -200,7 +200,6 @@ public function getAvailableUpdates(int $eid, string $minimumStability = self::S $updateObjects = []; foreach ($results as $result) { - $updateElements = $this->getUpdateObjectsForSite($result, $minimumStability); foreach ($updateElements as $updateElement) { From 175423f651e8ee7d733ae28a6204fb81085a9190 Mon Sep 17 00:00:00 2001 From: hleithner Date: Sun, 17 Nov 2024 21:45:57 +0100 Subject: [PATCH 036/130] Implement update server registration. --- .../components/com_joomlaupdate/config.xml | 5 + .../src/Extension/JoomlaupdateComponent.php | 136 +++++++++++++++--- .../language/en-GB/com_joomlaupdate.ini | 4 + components/com_config/src/Service/Router.php | 2 +- installation/src/Helper/DatabaseHelper.php | 2 +- libraries/src/Updater/ConstraintChecker.php | 1 + libraries/src/Version.php | 2 +- 7 files changed, 128 insertions(+), 24 deletions(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index 149401eb167ee..0ebe422d7906d 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -90,6 +90,11 @@ + + getName() !== 'com_config.component') - { + if ($form->getName() !== 'com_config.component') { return; } @@ -53,8 +60,7 @@ public function prepareForm(Form $form, $data) : void $token = $config->get('update_token'); - if (empty($token)) - { + if (empty($token)) { $token = UserHelper::genRandomPassword(40); } @@ -65,31 +71,119 @@ public function prepareForm(Form $form, $data) : void // Handle automated updates when form is submitted (but before it's saved) $input = Factory::getApplication()->getInput(); - if ($input->getMethod() === 'POST') - { - $this->manageAutoUpdate($data); + if ($input->getMethod() === 'POST') { + $dispatcher = Factory::getApplication()->getDispatcher(); + $dispatcher->addListener('onExtensionBeforeSave', [$this, 'onExtensionBeforeSave']); + $dispatcher->addListener('onExtensionAfterSave', [$this, 'onExtensionAfterSave']); } } /** - * Decide if we subscribe or unsubscribe from automated updates - * - * @param array|object $data + * Handles subscribe or unsubscribe from automated updates * + * @param $event * @return void + * @throws \Exception */ - protected function manageAutoUpdate($data) { - if (empty($data['autoupdate']) || $data['updatesource'] !== 'default' || $data['minimum_stability'] !== 'stable') - { - if (!empty($data['update_token'])) { - // @todo implement - // $this->autoUpdateUnsubscribe($data['update_token']); + public function onExtensionBeforeSave(\Joomla\CMS\Event\Model\BeforeSaveEvent $event) + { + $context = $event->getArgument('context'); + $table = $event->getArgument('subject'); + + if ($context !== 'com_config.component') { + return; + } + + $data = new Registry($table->params); + + if ($data->get('updatesource') !== 'default' || $data->get('minimum_stability') !== '4') { + if ((int)$data->get('autoupdate_status') === 1) { + $data->set('autoupdate_status', 2); + } else { + $data->set('autoupdate_status', 1); } + $table->params = $data->toString(); + } else if ((int) $data->get('autoupdate') === 0) { + if ((int) $data->get('autoupdate_status') === 1) { + $data->set('autoupdate_status', 2); + } else { + $data->set('autoupdate_status', 1); + } + $table->params = $data->toString(); + } else { + $data->set('autoupdate_status', 0); + $table->params = $data->toString(); + } + } + + public function onExtensionAfterSave(\Joomla\CMS\Event\Model\AfterSaveEvent $event) + { + $context = $event->getArgument('context'); + $table = $event->getArgument('subject'); + if ($context !== 'com_config.component') { return; } - // @todo implement - // $this->autoUpdateSubscribe($data['update_token']); + $data = new Registry($table->params); + + if (empty($data->get('update_token'))) { + return; + } + + // We are already unsubscribed + if ($data->get('autoupdate_status') === 2) { + return; + } + + $register = true; + if ((int)$data->get('autoupdate') !== 1 || (int)$data->get('autoupdate_status') !== 0) { + $register = false; + } + + $http = HttpFactory::getHttp(); + + $url = 'https://autoupdate.joomla.org/api/v1'; + + if ($register) { + $url .= '/register'; + } else { + $url .= '/delete'; + } + + $requestData = [ + 'url' => Route::link('site', 'index.php', false, Route::TLS_IGNORE, true), + 'key' => $data->get('update_token'), + ]; + + // JHttp transport throws an exception when there's no response. + try { + $response = $http->post($url, json_encode($requestData), [ + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ], 20); + } catch (\RuntimeException $e) { + $response = null; + Factory::getApplication()->enqueueMessage($e->getMessage(), 'error'); + } + + if ($response->getStatusCode() === 200) { + $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS'; + if (!$register) { + $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS'; + } + + Factory::getApplication()->enqueueMessage(Text::_($message), 'info'); + + return; + } + + $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR'; + if (!$register) { + $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR'; + } + + $result = json_decode((string)$response->getBody(), true); + Factory::getApplication()->enqueueMessage(Text::sprintf($message, $result['message'], $result['status']), 'error'); } } diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index b807f02fd57b6..3f2da9f4c9dc4 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -3,6 +3,10 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 +COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS="Successful registered to autoupdate service" +COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR="Error while registering to autoupdate service: %s (%d)" +COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Successful unregistered from autoupdate service" +COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from autoupdate service: %s (%d)" COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." COM_JOOMLAUPDATE_CONFIG_AUTO_UPDATE_DISABLED_LABEL=" Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." diff --git a/components/com_config/src/Service/Router.php b/components/com_config/src/Service/Router.php index 30cfd33bb6c5f..9df4387dbcf37 100644 --- a/components/com_config/src/Service/Router.php +++ b/components/com_config/src/Service/Router.php @@ -5,7 +5,7 @@ * @subpackage com_config * * @copyright (C) 2009 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt +* @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Config\Site\Service; diff --git a/installation/src/Helper/DatabaseHelper.php b/installation/src/Helper/DatabaseHelper.php index aa4f1351a7fb1..a9f4867c00776 100644 --- a/installation/src/Helper/DatabaseHelper.php +++ b/installation/src/Helper/DatabaseHelper.php @@ -45,7 +45,7 @@ abstract class DatabaseHelper * @var string * @since 4.0.0 */ - protected static $dbMinimumMySql = '8.0.13'; + protected static $dbMinimumMySql = '5.0.13'; /** * The minimum database server version for PostgreSQL databases as required by the CMS. diff --git a/libraries/src/Updater/ConstraintChecker.php b/libraries/src/Updater/ConstraintChecker.php index 26a38445a882e..80840bfc7b0ad 100644 --- a/libraries/src/Updater/ConstraintChecker.php +++ b/libraries/src/Updater/ConstraintChecker.php @@ -226,6 +226,7 @@ protected function checkSupportedDatabases(array $supportedDatabases) $dbType = 'mariadb'; } } + return true; // Do we have an entry for the database? if (!empty($supportedDatabases["$dbType"])) { diff --git a/libraries/src/Version.php b/libraries/src/Version.php index 08a24fe778068..d83cedc3467ea 100644 --- a/libraries/src/Version.php +++ b/libraries/src/Version.php @@ -47,7 +47,7 @@ final class Version * @var integer * @since 3.8.0 */ - public const MINOR_VERSION = 3; + public const MINOR_VERSION = 1; /** * Patch release version. From 344cce089c43ed8d0c49d8ea2a5da0ec9d77a648 Mon Sep 17 00:00:00 2001 From: Harald Leithner Date: Mon, 18 Nov 2024 09:22:55 +0100 Subject: [PATCH 037/130] Update components/com_config/src/Service/Router.php --- components/com_config/src/Service/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/com_config/src/Service/Router.php b/components/com_config/src/Service/Router.php index 9df4387dbcf37..6a9c74b5a5ed3 100644 --- a/components/com_config/src/Service/Router.php +++ b/components/com_config/src/Service/Router.php @@ -5,7 +5,7 @@ * @subpackage com_config * * @copyright (C) 2009 Open Source Matters, Inc. -* @license GNU General Public License version 2 or later; see LICENSE.txt + * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Config\Site\Service; From 529178e47d74d7c13e2f45c269f66388334a03d7 Mon Sep 17 00:00:00 2001 From: Harald Leithner Date: Mon, 18 Nov 2024 09:23:02 +0100 Subject: [PATCH 038/130] Update libraries/src/Version.php --- libraries/src/Version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/src/Version.php b/libraries/src/Version.php index d83cedc3467ea..08a24fe778068 100644 --- a/libraries/src/Version.php +++ b/libraries/src/Version.php @@ -47,7 +47,7 @@ final class Version * @var integer * @since 3.8.0 */ - public const MINOR_VERSION = 1; + public const MINOR_VERSION = 3; /** * Patch release version. From e43fc8622a11210cc12d97a66d0ff472c87290e6 Mon Sep 17 00:00:00 2001 From: Harald Leithner Date: Mon, 18 Nov 2024 09:23:08 +0100 Subject: [PATCH 039/130] Update libraries/src/Updater/ConstraintChecker.php --- libraries/src/Updater/ConstraintChecker.php | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/src/Updater/ConstraintChecker.php b/libraries/src/Updater/ConstraintChecker.php index 80840bfc7b0ad..26a38445a882e 100644 --- a/libraries/src/Updater/ConstraintChecker.php +++ b/libraries/src/Updater/ConstraintChecker.php @@ -226,7 +226,6 @@ protected function checkSupportedDatabases(array $supportedDatabases) $dbType = 'mariadb'; } } - return true; // Do we have an entry for the database? if (!empty($supportedDatabases["$dbType"])) { From dc8460612486563d7089e9b290089101d6f13199 Mon Sep 17 00:00:00 2001 From: Harald Leithner Date: Mon, 18 Nov 2024 09:23:13 +0100 Subject: [PATCH 040/130] Update installation/src/Helper/DatabaseHelper.php --- installation/src/Helper/DatabaseHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation/src/Helper/DatabaseHelper.php b/installation/src/Helper/DatabaseHelper.php index a9f4867c00776..aa4f1351a7fb1 100644 --- a/installation/src/Helper/DatabaseHelper.php +++ b/installation/src/Helper/DatabaseHelper.php @@ -45,7 +45,7 @@ abstract class DatabaseHelper * @var string * @since 4.0.0 */ - protected static $dbMinimumMySql = '5.0.13'; + protected static $dbMinimumMySql = '8.0.13'; /** * The minimum database server version for PostgreSQL databases as required by the CMS. From 5924f40019ca151017724091d596d8088db0c397 Mon Sep 17 00:00:00 2001 From: Harald Leithner Date: Mon, 18 Nov 2024 09:23:54 +0100 Subject: [PATCH 041/130] Update components/com_config/src/Service/Router.php --- components/com_config/src/Service/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/com_config/src/Service/Router.php b/components/com_config/src/Service/Router.php index 6a9c74b5a5ed3..30cfd33bb6c5f 100644 --- a/components/com_config/src/Service/Router.php +++ b/components/com_config/src/Service/Router.php @@ -5,7 +5,7 @@ * @subpackage com_config * * @copyright (C) 2009 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt + * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Config\Site\Service; From bb3be61156d3813ea0f2b73453ae9f939dae8509 Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 18 Jan 2025 16:03:09 +0100 Subject: [PATCH 042/130] Implement quickicon --- .../sql/updates/mysql/5.3.0-2025-01-18.sql | 3 + .../updates/postgresql/5.3.0-2025-01-18.sql | 3 + .../src/Controller/UpdateController.php | 31 ++++ .../en-GB/plg_quickicon_autoupdate.ini | 15 ++ .../en-GB/plg_quickicon_autoupdate.sys.ini | 7 + .../js/healthcheck.es6.js | 57 +++++++ installation/sql/mysql/base.sql | 15 +- installation/sql/postgresql/base.sql | 15 +- plugins/quickicon/autoupdate/autoupdate.xml | 34 +++++ .../autoupdate/services/provider.php | 49 ++++++ .../autoupdate/src/Extension/Autoupdate.php | 141 ++++++++++++++++++ 11 files changed, 356 insertions(+), 14 deletions(-) create mode 100644 administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql create mode 100644 administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql create mode 100644 administrator/language/en-GB/plg_quickicon_autoupdate.ini create mode 100644 administrator/language/en-GB/plg_quickicon_autoupdate.sys.ini create mode 100644 build/media_source/plg_quickicon_autoupdate/js/healthcheck.es6.js create mode 100644 plugins/quickicon/autoupdate/autoupdate.xml create mode 100644 plugins/quickicon/autoupdate/services/provider.php create mode 100644 plugins/quickicon/autoupdate/src/Extension/Autoupdate.php diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql new file mode 100644 index 0000000000000..cd39b8703435c --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql @@ -0,0 +1,3 @@ +INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) +SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'autoupdate' AND e.`folder` = 'quickicon' AND e.`client_id` = 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql new file mode 100644 index 0000000000000..f21c5c4b7cc6a --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql @@ -0,0 +1,3 @@ +INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") +SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'autoupdate' AND e."folder" = 'quickicon' AND e."client_id" = 0); diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 53ea811db91fa..e6f1fe0a6cea9 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -10,6 +10,7 @@ namespace Joomla\Component\Joomlaupdate\Administrator\Controller; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Language\Text; @@ -712,4 +713,34 @@ public function ajax() $this->app->close(); } + + /** + * Fetch and report health status of the auto update in \JSON format, for AJAX requests + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function healthstatus() + { + if (!Session::checkToken('get')) { + $this->app->setHeader('status', 403, true); + $this->app->sendHeaders(); + echo Text::_('JINVALID_TOKEN_NOTICE'); + $this->app->close(); + } + + $params = ComponentHelper::getParams('com_joomlaupdate'); + + $lastCheck = date_create_from_format('Y-m-d H:i:s', $params->get('update_last_check', '')); + + $result = [ + 'active' => (int) $params->get('autoupdate'), + 'healthy' => $lastCheck !== false && $lastCheck->diff(new \DateTime())->days < 4, + ]; + + echo json_encode($result); + + $this->app->close(); + } } diff --git a/administrator/language/en-GB/plg_quickicon_autoupdate.ini b/administrator/language/en-GB/plg_quickicon_autoupdate.ini new file mode 100644 index 0000000000000..8eae5aa40a6b3 --- /dev/null +++ b/administrator/language/en-GB/plg_quickicon_autoupdate.ini @@ -0,0 +1,15 @@ +; Joomla! Project +; (C) 2025 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Auto Update Health Notification" +PLG_QUICKICON_AUTOUPDATE_CHECKING="Checking Auto Update …" +PLG_QUICKICON_AUTOUPDATE_DISABLED="Automated Updates are disabled." +PLG_QUICKICON_AUTOUPDATE_ERROR="Unknown Health status …" +PLG_QUICKICON_AUTOUPDATE_GROUP_DESC="The group of this plugin (this value is compared with the group value used in Quick Icons modules to inject icons)." +PLG_QUICKICON_AUTOUPDATE_GROUP_LABEL="Group" +PLG_QUICKICON_AUTOUPDATE_OK="Automates Updates working." +PLG_QUICKICON_AUTOUPDATE_OUTDATED="Automates Updates Connection broken." +PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of auto updates and notifies you when you visit the Home Dashboard page." + diff --git a/administrator/language/en-GB/plg_quickicon_autoupdate.sys.ini b/administrator/language/en-GB/plg_quickicon_autoupdate.sys.ini new file mode 100644 index 0000000000000..cdcadc5c384f4 --- /dev/null +++ b/administrator/language/en-GB/plg_quickicon_autoupdate.sys.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2025 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Auto Update Health Notification" +PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of auto updates and notifies you when you visit the Home Dashboard page." diff --git a/build/media_source/plg_quickicon_autoupdate/js/healthcheck.es6.js b/build/media_source/plg_quickicon_autoupdate/js/healthcheck.es6.js new file mode 100644 index 0000000000000..0b2deaf0e6517 --- /dev/null +++ b/build/media_source/plg_quickicon_autoupdate/js/healthcheck.es6.js @@ -0,0 +1,57 @@ +/** + * @copyright (C) 2025 Open Source Matters, Inc. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +if (Joomla && Joomla.getOptions('js-auto-update')) { + const update = (type, text) => { + const link = document.getElementById('plg_quickicon_autoupdate'); + if (link) { + link.classList.add(type); + } + + link.querySelectorAll('span.j-links-link').forEach((span) => { + span.innerHTML = Joomla.sanitizeHtml(text); + }); + }; + + const checkHealthStatus = () => { + const options = Joomla.getOptions('js-auto-update'); + + /** + * DO NOT use fetch() for QuickIcon requests. They must be queued. + * + * @see https://github.com/joomla/joomla-cms/issues/38001 + */ + Joomla.enqueueRequest({ + url: options.ajaxUrl, + method: 'GET', + promise: true, + }).then((xhr) => { + const response = xhr.responseText; + const healthStatus = JSON.parse(response); + + if (healthStatus) { + // Not active + if (!healthStatus.active) { + update('warning', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_DISABLED')); + } else { + if (!healthStatus.healthy) { + update('danger', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_OUTDATED')); + } else { + update('success', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_OK')); + } + } + } else { + // An error occurred + update('danger', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_ERROR')); + } + }).catch(() => { + // An error occurred + update('danger', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_ERROR')); + }); + }; + + // Give some times to the layout and other scripts to settle their stuff + window.addEventListener('load', () => setTimeout(checkHealthStatus, 300)); +} diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index afa2ca94d1577..ec38c008deb35 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -325,13 +325,14 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'plg_privacy_content', 'plugin', 'content', 'privacy', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), (0, 'plg_privacy_message', 'plugin', 'message', 'privacy', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), (0, 'plg_privacy_user', 'plugin', 'user', 'privacy', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), -(0, 'plg_quickicon_joomlaupdate', 'plugin', 'joomlaupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 1, 0), -(0, 'plg_quickicon_extensionupdate', 'plugin', 'extensionupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 2, 0), -(0, 'plg_quickicon_overridecheck', 'plugin', 'overridecheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 3, 0), -(0, 'plg_quickicon_downloadkey', 'plugin', 'downloadkey', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 4, 0), -(0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), -(0, 'plg_quickicon_phpversioncheck', 'plugin', 'phpversioncheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 6, 0), -(0, 'plg_quickicon_eos', 'plugin', 'eos', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 7, 0), +(0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 1, 0), +(0, 'plg_quickicon_joomlaupdate', 'plugin', 'joomlaupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 2, 0), +(0, 'plg_quickicon_extensionupdate', 'plugin', 'extensionupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 3, 0), +(0, 'plg_quickicon_overridecheck', 'plugin', 'overridecheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 4, 0), +(0, 'plg_quickicon_downloadkey', 'plugin', 'downloadkey', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 5, 0), +(0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), +(0, 'plg_quickicon_phpversioncheck', 'plugin', 'phpversioncheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 7, 0), +(0, 'plg_quickicon_eos', 'plugin', 'eos', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 8, 0), (0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_sampledata_multilang', 'plugin', 'multilang', 'sampledata', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_schemaorg_article', 'plugin', 'article', 'schemaorg', 0, 1, 1, 0, 0, '', '{}', '', 1, 0), diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index 7d89b0cf41c98..a90503f36ef49 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -331,13 +331,14 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'plg_privacy_content', 'plugin', 'content', 'privacy', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), (0, 'plg_privacy_message', 'plugin', 'message', 'privacy', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), (0, 'plg_privacy_user', 'plugin', 'user', 'privacy', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), -(0, 'plg_quickicon_joomlaupdate', 'plugin', 'joomlaupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 1, 0), -(0, 'plg_quickicon_extensionupdate', 'plugin', 'extensionupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 2, 0), -(0, 'plg_quickicon_overridecheck', 'plugin', 'overridecheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 3, 0), -(0, 'plg_quickicon_downloadkey', 'plugin', 'downloadkey', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 4, 0), -(0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), -(0, 'plg_quickicon_phpversioncheck', 'plugin', 'phpversioncheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 6, 0), -(0, 'plg_quickicon_eos', 'plugin', 'eos', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 7, 0), +(0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 1, 0), +(0, 'plg_quickicon_joomlaupdate', 'plugin', 'joomlaupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 2, 0), +(0, 'plg_quickicon_extensionupdate', 'plugin', 'extensionupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 3, 0), +(0, 'plg_quickicon_overridecheck', 'plugin', 'overridecheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 4, 0), +(0, 'plg_quickicon_downloadkey', 'plugin', 'downloadkey', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 5, 0), +(0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), +(0, 'plg_quickicon_phpversioncheck', 'plugin', 'phpversioncheck', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 7, 0), +(0, 'plg_quickicon_eos', 'plugin', 'eos', 'quickicon', 0, 1, 1, 0, 1, '', '', '', 8, 0), (0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_sampledata_multilang', 'plugin', 'multilang', 'sampledata', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_schemaorg_article', 'plugin', 'article', 'schemaorg', 0, 1, 1, 0, 0, '', '{}', '', 1, 0), diff --git a/plugins/quickicon/autoupdate/autoupdate.xml b/plugins/quickicon/autoupdate/autoupdate.xml new file mode 100644 index 0000000000000..d858b03624019 --- /dev/null +++ b/plugins/quickicon/autoupdate/autoupdate.xml @@ -0,0 +1,34 @@ + + + plg_quickicon_autoupdate + Joomla! Project + 2025-01 + (C) 2025 Open Source Matters, Inc. + GNU General Public License version 2 or later; see LICENSE.txt + admin@joomla.org + www.joomla.org + 5.0.0 + PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION + Joomla\Plugin\Quickicon\Autoupdate + + services + src + + + language/en-GB/plg_quickicon_autoupdate.ini + language/en-GB/plg_quickicon_autoupdate.sys.ini + + + +
+ +
+
+
+
diff --git a/plugins/quickicon/autoupdate/services/provider.php b/plugins/quickicon/autoupdate/services/provider.php new file mode 100644 index 0000000000000..99b431229e444 --- /dev/null +++ b/plugins/quickicon/autoupdate/services/provider.php @@ -0,0 +1,49 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +\defined('_JEXEC') or die; + +use Joomla\CMS\Extension\PluginInterface; +use Joomla\CMS\Factory; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; +use Joomla\Plugin\Quickicon\Autoupdate\Extension\Autoupdate; + +return new class () implements ServiceProviderInterface { + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * + * @since 4.0.0 + */ + public function register(Container $container) + { + $container->set( + PluginInterface::class, + function (Container $container) { + // @Todo This needs to be changed to a proper factory + $plugin = \Joomla\CMS\Plugin\PluginHelper::getPlugin('quickicon', 'autoupdate'); + + $plugin = new Autoupdate( + $container->get(DispatcherInterface::class), + Factory::getApplication()->getDocument(), + (array) $plugin + ); + $plugin->setApplication(Factory::getApplication()); + + return $plugin; + } + ); + } +}; diff --git a/plugins/quickicon/autoupdate/src/Extension/Autoupdate.php b/plugins/quickicon/autoupdate/src/Extension/Autoupdate.php new file mode 100644 index 0000000000000..573a594e51a8e --- /dev/null +++ b/plugins/quickicon/autoupdate/src/Extension/Autoupdate.php @@ -0,0 +1,141 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Plugin\Quickicon\Autoupdate\Extension; + +use Joomla\CMS\Document\Document; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\CMS\Session\Session; +use Joomla\CMS\Uri\Uri; +use Joomla\Event\DispatcherInterface; +use Joomla\Event\SubscriberInterface; +use Joomla\Module\Quickicon\Administrator\Event\QuickIconsEvent; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Joomla! auto update health check notification plugin + * + * @since __DEPLOY_VERSION__ + */ +class Autoupdate extends CMSPlugin implements SubscriberInterface +{ + /** + * Load the language file on instantiation. + * + * @var boolean + * @since __DEPLOY_VERSION__ + */ + protected $autoloadLanguage = true; + + /** + * The document. + * + * @var Document + * + * @since __DEPLOY_VERSION__ + */ + private $document; + + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onGetIcons' => 'getAutoUpdateStatusNotification', + ]; + } + + /** + * Constructor + * + * @param DispatcherInterface $dispatcher The object to observe + * @param Document $document The document + * @param array $config An optional associative array of configuration settings. + * Recognized key values include 'name', 'group', 'params', 'language' + * (this list is not meant to be comprehensive). + * + * @since __DEPLOY_VERSION__ + */ + public function __construct($dispatcher, Document $document, array $config = []) + { + parent::__construct($dispatcher, $config); + + $this->document = $document; + } + + /** + * This method is called when the Quick Icons module is constructing its set + * of icons. You can return an array which defines a single icon and it will + * be rendered right after the stock Quick Icons. + * + * @param QuickIconsEvent $event The event object + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function getAutoUpdateStatusNotification(QuickIconsEvent $event) + { + $context = $event->getContext(); + + if ( + $context !== $this->params->get('context', 'update_quickicon') + || !$this->getApplication()->getIdentity()->authorise('core.admin', 'com_joomlaupdate') + ) { + return; + } + + Text::script('PLG_QUICKICON_AUTOUPDATE_ERROR'); + Text::script('PLG_QUICKICON_AUTOUPDATE_OK'); + Text::script('PLG_QUICKICON_AUTOUPDATE_OUTDATED'); + Text::script('PLG_QUICKICON_AUTOUPDATE_DISABLED'); + Text::script('MESSAGE'); + Text::script('ERROR'); + Text::script('INFO'); + Text::script('WARNING'); + + $this->document->addScriptOptions( + 'js-auto-update', + [ + 'url' => Uri::base() . 'index.php?option=com_joomlaupdate', + 'ajaxUrl' => Uri::base() . 'index.php?option=com_joomlaupdate&task=update.healthstatus&' + . Session::getFormToken() . '=1', + ] + ); + + $this->document->getWebAssetManager() + ->registerAndUseScript('plg_quickicon_autoupdate', 'plg_quickicon_autoupdate/healthcheck.min.js', [], ['defer' => true], ['core']); + + // Add the icon to the result array + $result = $event->getArgument('result', []); + + $result[] = [ + [ + 'link' => 'index.php?option=com_config&view=component&component=com_joomlaupdate', + 'image' => 'icon-health', + 'icon' => '', + 'text' => Text::_('PLG_QUICKICON_AUTOUPDATE_CHECKING'), + 'id' => 'plg_quickicon_autoupdate', + 'group' => 'MOD_QUICKICON_MAINTENANCE', + ], + ]; + + $event->setArgument('result', $result); + } +} From a6e12e8e5f0a44c3051c33a992ee90f440f72260 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Mon, 20 Jan 2025 11:03:53 +0100 Subject: [PATCH 043/130] use correct site url --- .../com_joomlaupdate/src/Extension/JoomlaupdateComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php index c230f9de45dc3..c6822835e1115 100644 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -152,7 +152,7 @@ public function onExtensionAfterSave(\Joomla\CMS\Event\Model\AfterSaveEvent $eve } $requestData = [ - 'url' => Route::link('site', 'index.php', false, Route::TLS_IGNORE, true), + 'url' => Uri::root(), 'key' => $data->get('update_token'), ]; From 78780394369fbf0ffed617d0d81f48614d67a557 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Mon, 20 Jan 2025 11:17:13 +0100 Subject: [PATCH 044/130] fix input --- .../com_joomlaupdate/src/Controller/UpdatesController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php index 9252d3cf800e0..85109237a3ca4 100644 --- a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -77,7 +77,7 @@ public function prepareUpdate() $latestVersion = $model->getAutoUpdateVersion(); - $targetVersion = $this->input->getString('targetVersion'); + $targetVersion = $this->input->json->getString('targetVersion'); if (!$latestVersion || $latestVersion !== $targetVersion) { throw new \Exception(Text::_('COM_JOOMLAUPDATE_VIEW_UPDATE_VERSION_WRONG'), 410); From a05e1e3288f54c3e07c014f05f929b4805d5c1c5 Mon Sep 17 00:00:00 2001 From: hleithner Date: Sat, 22 Feb 2025 16:02:49 +0100 Subject: [PATCH 045/130] Rework register --- .../src/Enum/AutoupdateRegisterState.php | 24 +++++++ .../src/Enum/AutoupdateState.php | 22 ++++++ .../src/Extension/JoomlaupdateComponent.php | 69 ++++++++++--------- 3 files changed, 84 insertions(+), 31 deletions(-) create mode 100644 administrator/components/com_joomlaupdate/src/Enum/AutoupdateRegisterState.php create mode 100644 administrator/components/com_joomlaupdate/src/Enum/AutoupdateState.php diff --git a/administrator/components/com_joomlaupdate/src/Enum/AutoupdateRegisterState.php b/administrator/components/com_joomlaupdate/src/Enum/AutoupdateRegisterState.php new file mode 100644 index 0000000000000..4da394b41b645 --- /dev/null +++ b/administrator/components/com_joomlaupdate/src/Enum/AutoupdateRegisterState.php @@ -0,0 +1,24 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Administrator\Enum; + +\defined('_JEXEC') or die; + +/** + * Autoupdate State Enum + */ +enum AutoupdateRegisterState: int +{ + case Unsubscribe = -1; + case Unsubscribed = 0; + case Subscribe = 1; + case Subscribed = 2; +} diff --git a/administrator/components/com_joomlaupdate/src/Enum/AutoupdateState.php b/administrator/components/com_joomlaupdate/src/Enum/AutoupdateState.php new file mode 100644 index 0000000000000..cfaedc06dd038 --- /dev/null +++ b/administrator/components/com_joomlaupdate/src/Enum/AutoupdateState.php @@ -0,0 +1,22 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Administrator\Enum; + +\defined('_JEXEC') or die; + +/** + * Autoupdate State Enum + */ +enum AutoupdateState: int +{ + case Disabled = 0; + case Enabled = 1; +} diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php index c6822835e1115..da2fe2e0dce07 100644 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -18,13 +18,12 @@ use Joomla\CMS\Form\Form; use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Language\Text; -use Joomla\CMS\Router\Route; use Joomla\CMS\Uri\Uri; use Joomla\CMS\User\UserHelper; use Joomla\CMS\Version; -use Joomla\Http\TransportInterface; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateState; use Joomla\Registry\Registry; -use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -39,6 +38,8 @@ class JoomlaupdateComponent extends MVCComponent implements ConfigServiceInterfa { use ConfigServiceTrait; + private const autoupdateUrl = 'https://autoupdate.joomla.org/api/v1'; + /** * Prepares the config form * @@ -88,7 +89,7 @@ public function prepareForm(Form $form, $data): void public function onExtensionBeforeSave(\Joomla\CMS\Event\Model\BeforeSaveEvent $event) { $context = $event->getArgument('context'); - $table = $event->getArgument('subject'); + $table = $event->getArgument('subject'); if ($context !== 'com_config.component') { return; @@ -96,30 +97,29 @@ public function onExtensionBeforeSave(\Joomla\CMS\Event\Model\BeforeSaveEvent $e $data = new Registry($table->params); + $autoupdateStatus = (int)$data->get('autoupdate'); + $autoupdateRegisterStatus = (int)$data->get('autoupdate_status'); if ($data->get('updatesource') !== 'default' || $data->get('minimum_stability') !== '4') { - if ((int)$data->get('autoupdate_status') === 1) { - $data->set('autoupdate_status', 2); - } else { - $data->set('autoupdate_status', 1); + // If we are not using Joomla Update Server or not using Stable Version disable the autoupdate + if ($autoupdateRegisterStatus !== AutoupdateRegisterState::Unsubscribed->value) { + $data->set('autoupdate_status', AutoupdateRegisterState::Unsubscribe->value); } - $table->params = $data->toString(); - } else if ((int) $data->get('autoupdate') === 0) { - if ((int) $data->get('autoupdate_status') === 1) { - $data->set('autoupdate_status', 2); - } else { - $data->set('autoupdate_status', 1); + } elseif ($autoupdateStatus === AutoupdateState::Enabled->value) { + // If autoupdate is enabled and we are nor subscribed force subscription process + if ($autoupdateRegisterStatus !== AutoupdateRegisterState::Subscribed->value) { + $data->set('autoupdate_status', AutoupdateRegisterState::Subscribe->value); } - $table->params = $data->toString(); - } else { - $data->set('autoupdate_status', 0); - $table->params = $data->toString(); + } elseif ($autoupdateRegisterStatus !== AutoupdateRegisterState::Unsubscribed->value) { + // If autoupdate is disabled and we are not unsubscribed force unsubscription process + $data->set('autoupdate_status', AutoupdateRegisterState::Unsubscribe->value); } + $table->params = $data->toString(); } public function onExtensionAfterSave(\Joomla\CMS\Event\Model\AfterSaveEvent $event) { $context = $event->getArgument('context'); - $table = $event->getArgument('subject'); + $table = $event->getArgument('subject'); if ($context !== 'com_config.component') { return; @@ -131,21 +131,19 @@ public function onExtensionAfterSave(\Joomla\CMS\Event\Model\AfterSaveEvent $eve return; } - // We are already unsubscribed - if ($data->get('autoupdate_status') === 2) { + $autoupdateRegisterStatus = AutoupdateRegisterState::from((int)$data->get('autoupdate_status')); + // Check if action is required + if ($autoupdateRegisterStatus === AutoupdateRegisterState::Unsubscribed + || $autoupdateRegisterStatus === AutoupdateRegisterState::Subscribed + ) { return; } - $register = true; - if ((int)$data->get('autoupdate') !== 1 || (int)$data->get('autoupdate_status') !== 0) { - $register = false; - } - $http = HttpFactory::getHttp(); - $url = 'https://autoupdate.joomla.org/api/v1'; + $url = self::autoupdateUrl; - if ($register) { + if ($autoupdateRegisterStatus === AutoupdateRegisterState::Subscribe) { $url .= '/register'; } else { $url .= '/delete'; @@ -159,7 +157,7 @@ public function onExtensionAfterSave(\Joomla\CMS\Event\Model\AfterSaveEvent $eve // JHttp transport throws an exception when there's no response. try { $response = $http->post($url, json_encode($requestData), [ - 'Accept' => 'application/json', + 'Accept' => 'application/json', 'Content-Type' => 'application/json', ], 20); } catch (\RuntimeException $e) { @@ -169,8 +167,17 @@ public function onExtensionAfterSave(\Joomla\CMS\Event\Model\AfterSaveEvent $eve if ($response->getStatusCode() === 200) { $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS'; - if (!$register) { + $data->set('autoupdate_status', AutoupdateRegisterState::Subscribed->value); + + if ($autoupdateRegisterStatus === AutoupdateRegisterState::Unsubscribe) { $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS'; + $data->set('autoupdate_status', AutoupdateRegisterState::Unsubscribed->value); + } + + $table->params = $data->toString(); + + if (!$table->store()) { + throw new \RuntimeException($table->getError()); } Factory::getApplication()->enqueueMessage(Text::_($message), 'info'); @@ -179,7 +186,7 @@ public function onExtensionAfterSave(\Joomla\CMS\Event\Model\AfterSaveEvent $eve } $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR'; - if (!$register) { + if ($autoupdateRegisterStatus === AutoupdateRegisterState::Unsubscribe) { $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR'; } From f2cbfc3eedbc10b95c1cf11ae7567a91604f5d41 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Fri, 14 Mar 2025 22:35:36 +0100 Subject: [PATCH 046/130] Add entry-point if-case for autoupdate extraction process --- includes/app.php | 6 ------ index.php | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/includes/app.php b/includes/app.php index 349c7446f75cb..07a24430445ad 100644 --- a/includes/app.php +++ b/includes/app.php @@ -13,12 +13,6 @@ $startTime = microtime(1); $startMem = memory_get_usage(); -if (file_exists(\dirname(__DIR__) . '/defines.php')) { - include_once \dirname(__DIR__) . '/defines.php'; -} - -require_once __DIR__ . '/defines.php'; - // Check for presence of vendor dependencies not included in the git repository if (!file_exists(JPATH_LIBRARIES . '/vendor/autoload.php') || !is_dir(JPATH_PUBLIC . '/media/vendor')) { echo file_get_contents(JPATH_ROOT . '/templates/system/build_incomplete.html'); diff --git a/index.php b/index.php index 85daa024dce05..9609e4e6ccad3 100644 --- a/index.php +++ b/index.php @@ -28,5 +28,21 @@ */ define('_JEXEC', 1); +// Load global path definitions +if (file_exists(__DIR__ . '/defines.php')) { + include_once __DIR__ . '/defines.php'; +} + +require_once __DIR__ . '/includes/defines.php'; + +// Check the existence of an update-extraction config file +if ($_GET['jautoupdate'] === '1' && file_exists(JPATH_ADMINISTRATOR . '/components/com_joomlaupdate/update.php')) { + // Load extraction script and... + require_once JPATH_ADMINISTRATOR . '/components/com_joomlaupdate/extract.php'; + + // ... die + die(); +} + // Run the application - All executable code should be triggered through this file -require_once dirname(__FILE__) . '/includes/app.php'; +require_once __DIR__ . '/includes/app.php'; From 5707f645e8699d96b796edf55c09a3609eac8563 Mon Sep 17 00:00:00 2001 From: Brian Teeman Date: Fri, 14 Mar 2025 22:10:23 +0000 Subject: [PATCH 047/130] Update JoomlaupdateComponent.php --- .../com_joomlaupdate/src/Extension/JoomlaupdateComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php index da2fe2e0dce07..ddee8c1f60dc3 100644 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php @@ -105,7 +105,7 @@ public function onExtensionBeforeSave(\Joomla\CMS\Event\Model\BeforeSaveEvent $e $data->set('autoupdate_status', AutoupdateRegisterState::Unsubscribe->value); } } elseif ($autoupdateStatus === AutoupdateState::Enabled->value) { - // If autoupdate is enabled and we are nor subscribed force subscription process + // If autoupdate is enabled and we are not subscribed force subscription process if ($autoupdateRegisterStatus !== AutoupdateRegisterState::Subscribed->value) { $data->set('autoupdate_status', AutoupdateRegisterState::Subscribe->value); } From 206a28ffc97d2c86057d4ac024a8d652d5e697e9 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Fri, 14 Mar 2025 23:49:11 +0100 Subject: [PATCH 048/130] Added joomlaupdate webservice plugin to install and update SQL --- .../com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql | 4 ++++ .../com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql | 4 ++++ installation/sql/mysql/base.sql | 1 + installation/sql/postgresql/base.sql | 1 + 4 files changed, 10 insertions(+) diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql index cd39b8703435c..5dd0589e35e85 100644 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql +++ b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql @@ -1,3 +1,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'autoupdate' AND e.`folder` = 'quickicon' AND e.`client_id` = 0); + +INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) +SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'joomlaupdate' AND e.`folder` = 'webservices' AND e.`client_id` = 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql index f21c5c4b7cc6a..393ba9b51abff 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql @@ -1,3 +1,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'autoupdate' AND e."folder" = 'quickicon' AND e."client_id" = 0); + +INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") +SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'joomlaupdate' AND e."folder" = 'webservices' AND e."client_id" = 0); diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index 49cfc463e206e..322ee28b13498 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -392,6 +392,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'plg_webservices_contact', 'plugin', 'contact', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), (0, 'plg_webservices_content', 'plugin', 'content', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), (0, 'plg_webservices_installer', 'plugin', 'installer', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), +(0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), (0, 'plg_webservices_languages', 'plugin', 'languages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), (0, 'plg_webservices_media', 'plugin', 'media', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), (0, 'plg_webservices_menus', 'plugin', 'menus', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index 54efdb332c891..56b2ea8f1918b 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -398,6 +398,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'plg_webservices_contact', 'plugin', 'contact', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), (0, 'plg_webservices_content', 'plugin', 'content', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), (0, 'plg_webservices_installer', 'plugin', 'installer', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), +(0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), (0, 'plg_webservices_languages', 'plugin', 'languages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), (0, 'plg_webservices_media', 'plugin', 'media', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), (0, 'plg_webservices_menus', 'plugin', 'menus', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), From 022a3ac0698e0b4f5cb8886560a66fa3baacf67c Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 15 Mar 2025 12:23:29 +0100 Subject: [PATCH 049/130] Enhance guided tours for Joomla 5.3 with new automated updates feature and updated descriptions --- .../sql/updates/mysql/5.3.0-2025-03-14.sql | 9 +++++++-- .../sql/updates/postgresql/5.3.0-2025-03-14.sql | 9 +++++++-- .../en-GB/guidedtours.joomla_whatsnew_5_3.ini | 2 +- .../guidedtours.joomla_whatsnew_5_3_steps.ini | 6 ++++-- .../images/5_3/automated-updates.jpg | Bin 0 -> 23825 bytes 5 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 build/media_source/com_guidedtours/images/5_3/automated-updates.jpg diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql index 2eedbb010e52d..5a9a4f6981ac4 100644 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql +++ b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql @@ -5,6 +5,11 @@ INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `publ ('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-3', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0); INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'center', '', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 FROM `#__guidedtours` - WHERE `uid` = 'joomla-whatsnew-5-3'; + WHERE `uid` = 'joomla-whatsnew-5-3'; + +INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 + FROM `#__guidedtours` + WHERE `uid` = 'joomla-whatsnew-5-3'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql index cfb58259717f7..85624c9abbbe9 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql @@ -5,6 +5,11 @@ INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "publ ('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-3', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0); INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'center', '', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 FROM "#__guidedtours" - WHERE "uid" = 'joomla-whatsnew-5-3'; + WHERE "uid" = 'joomla-whatsnew-5-3'; + +INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 + FROM "#__guidedtours" + WHERE "uid" = 'joomla-whatsnew-5-3'; diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini index 279928d33f031..b9a4ab376d870 100644 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini @@ -3,5 +3,5 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION="

Welcome to Joomla 5.3!

Guided Tours Updates

Guided Tours now has its own API. Joomla API Documentation

Stay tuned for other new enhancements coming soon!

\"The

Core Updates

Organize Files in their Own Location

Now you can see and select your stored/uploaded documents directly from the Media Manager. Find more information in the Joomla Community Magazine.

View Scheduled Task History

You now have the ability to view execution information directly in the backend without having to access log files. Look for the Execution History button located in the Scheduled Tasks page.

Other Enhancements and Fixes

  • Template Override Plugin Comparison - adds compare functionality to plugin overrides
  • Tag Alias Lookup Fixed - now instead of showing the tag id number in the URL the tag name is shown
" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION="

Welcome to Joomla 5.3!

\"Display

Automated Updates are here!

Joomla! 5.3 now supports automated updates for better security and performance.

Enable your automated updates now

Stay safe and secure!

" COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE="What’s New in Joomla 5.3!" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini index fe8788b793d8c..b474b42b47738 100644 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini @@ -3,5 +3,7 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION="

Joomla 5.3 Full Release Notes

View the full release notes on joomla.org


Help and Information

Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.

" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE="More Information and Help" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_DESCRIPTION="

Joomla 5.3 Full Release Notes

View the full release notes on joomla.org


Help and Information

Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_TITLE="More Information and Help" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION="

More mentionable features

Guided Tours Updates

Guided Tours now has its own API. Joomla API Documentation

Stay tuned for other new enhancements coming soon!

\"The

Core Updates

Organize Files in their Own Location

Now you can see and select your stored/uploaded documents directly from the Media Manager. Find more information in the Joomla Community Magazine.

View Scheduled Task History

You now have the ability to view execution information directly in the backend without having to access log files. Look for the Execution History button located in the Scheduled Tasks page.

Other Enhancements and Fixes

  • Template Override Plugin Comparison - adds compare functionality to plugin overrides
  • Tag Alias Lookup Fixed - now instead of showing the tag id number in the URL the tag name is shown
" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE="More mentionable features" diff --git a/build/media_source/com_guidedtours/images/5_3/automated-updates.jpg b/build/media_source/com_guidedtours/images/5_3/automated-updates.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8e6b91a5f016ba7585111fd2cfa8379b0da18824 GIT binary patch literal 23825 zcmeEubwC}>vgZK~?i}2m;O-FIf(3V%;2JErySoQ>cL>3QLvVL@f`$NLNxm;%?%R9! z-n(!2z5Qp0Ij5(qtE;Pfs;YlIJ%^|Hr*#0zD{(1t02mkm0QUR`cv=F80DutB2l$U~ zAP@)%1qTHM2?>P&0}Bm@gn*2Mgn)>MjEV_DM!`TuLi|N6LqI`;!917ZJ=1>_{!J+uIK*=opq~~22oTRzQ6NyB>ph+n2>z=6f0`0Hy;GHO ze%m;Gg~|p(cO;NC9b_`lWA=#oXM!PmV-LP?P6Cj}-FMChE+QQlZ3F!1+IX}^>c?Bh zzDh^8zYEj4USs@cT0(s3B_5v3IlTb5es8&Y+i)cppt#7{I~M4aC)9{Hm8;RCu{PWJ zPqYBrL8;-#{bx=5lgfWzgm^bEGMZ`pyI_)hfzT3@^)~@_s&XLhZW!C=FA~&X{r+c9 zpf-JN(qA-yK|A>>X$fKdZwhSk)LYG3=KJ3iC{=Y1fLQkuwZXVYf05SaJJ6#IL;Mln zuTh6UJfQr7A$k4&cNLkB>A5qp(euA4EVW(L;0%}x()JyYSNPGLj|j-LwLLT22Op=p zPrW7XepSY{mEsI3m8ke#6Wru#1+zTDtMe}sSYi^Q52{_`ke1Iw(-E}?vPk12-mdG~ z`1dFm8^Y*sx1W6ebnQ}e>)VAMo9tjZsDdMlbKlHDAd`wZ@ zi>~_SHD3DdW$~X3U@YHk!d1lu3`)sHUHQh*FFr`)9UK#8*B$VG|J52od9@WFJg`x5 z@ltea4gc-1)%NvPoBA&aL09pvVfpVqyFLL@w=T4oJ-iu-4)t=rl|?%L&mCd!^)f&A zdNcBsuj@FgsO}s5;y08(d2lrJ=fSYxtqNMQ=pXiaPn!;gVT?d;+PN#~cMf#e>(eL2 z6PIY@_*JDR>l%s-4jk;htC_ZrS9ubpUjYD2t8uod%F&w0Ljv3vp22D+NLlQSKFe@#dC8_C}j?bTkCMN#+KTUqi<20N2u0yTm+I64nWNs|a_1&yoT*>sZOWqJ#@S1+I2 z_+^_tLF4Js<8WqUr;CPKvinCF2aN&mkTP}OB$MAYNn4xeCOc1sjc2z_6^&kQ@1Im4 zvRu)>yN~1n0RB?&{mxwG=9*`22kk)n>lLRxT>@xT!9O(n<)rwO9t%XEMoE#71I7w% zC1nXJ8GbU|kA^8%$#ZFi8Zu|{@}A{|oxj!UF09`v2~y%NGPuz+B$v(Wvw0(D*u1(V z4cn2mH$1hYXOOwKV|$3B7Z9nOu2_=JoHYN%J1tc zwA;ek(Q0v&dJ(Y}?jJr1T@fjy3I56QV;brF#r`9G z9{4(mBz#6JzzHvJD}C#)GQ_0RQN!nH4B|QR4b;ECMwXaaVfnN0A1lQ@oE%-mpRo3d zQntiAL&dhD%B4s?YiEe}XIG)HoA_YQ15nq<9iZx`9bl$CNC6Kka4MM9>dYVQ^MxWkN`IMX@1 zP&b>@<_a3$|GgEd_S5+Mr4Syy`RG6JbmG4lo-ZsU27Ug@L)mi|ZInI_%CF;FW)1PL z>*o|=<9Xuvm&Z%o3Z0qif5`>_gVywZhMhtv05IS)(1Zd)0AU~@pX)(@J%dhg05mGP zG71`q&Cr2GP(cX>gBX*9^)(hYGrOXSz9T6Ur;r^Phw59WXK)Jhj9J0Z08fB{WS#xu zNvjmq#PS(GZ|1MVh^Sw~mdsfj^<5P0S)t>AdfRha*U~oYOETKKX!PO9>b0ml3^O5G z%7`|v6d_A<0YCo8qlXRYF4V5o^jgKwy162ziUi$gilzH%d_g$b6>e5+nN?vn+KYi7s3UX|3XIIJ#M6?V2v)UUfMn1f#Obi@oLyesiUwlmYVo< z&YXrEQo$x(VY6CKw~r^aRv@-`Vp+*?jl0DUZ3q)FZk*Pz#tVnj2FclZCZ#l<9wR3I z4OQc%OAxksORA9Ai9&uSO~g)j4R777%JSfnxJ#clMQ-WT+zlSD;0m~nb<1VH>M_YE z-kUn@jayaIVSdj#c7Kde-0IXPfVhqGyseYtyAzjJR$>lr4LhpHOnsW1yvCF1U)^)F z8u%T%j*5^qy$Cq7wCv)%3fx~nx&(T>eLH@|^T2*m>Ra2DzhWcRXreIu`6eh&FxG_` zzg96mn)#F~twHff&D084W6N#5|0905wh70#Z1!emwNPw@v@VceWcuzBQ3E|E{LM-O zMG(l$#4d`0!`*tf0_}zyw^N#mX`B*yxpwKDw#PAWn9F8s9|{%&+v>*B8eYsrj{h}O zfb%UiTBAIIT(JM>KE;D3*MHxZFA)xu&2s=E}^DhGf_5xz$dB zjXglKamd=5VIecEM%K7niF^=cb78azl9D5rW)H?}0X@-dVR!JvIC6{DeaMk?c>AqW zs`o@&PYsh+ABC?b!ta+4dOLzsM;0 zZMU!TuW7KaT*vGD*Cmo+;eD**QGUgO>tdpEH`ITqz@GI=*tjf7GBj>8^uMG_Y{$eKJ@1R&)r$NsL{vI*IjF>MLOyMs#Wso(dU5ct#2j~w zd<+k>!lWF)$>xhEmF9JR$A*{3!;DW7QEVLFK#SoXeivvJ-X#k-S;aWQ8_`b1|7tk= zX=yMOmW0pZaqP`GZ>qk0l00{C9YcQy%(H>x>v|Ze2mG#!w4%HOLCGw!X)Q|)<=^{5@@?Nz1{pr z|GT%BDef%C?&slaOJr>c^KCXxw{jV-&7dyYfc26-tf->BEm|h3lq8nOYFE<39M7ti zfDMDomypnq#4mN4;*e{2L7U@i$@|M?bI0t)a#{gYUfWsNkP;10TQb%xe9Sm1%5RW| zqer2aI|`Z-vFZp%M^Q1keQSE6ut9Vx#vKRCMECulkE8pQ#~|>*hK7{|QU05?4GLC6`B=Ejf{)GgV*qGY(-891P9kVIT$ADWXI- zZN@EyvE#?D<(?u=H@WNWzQFJNEYd3owQ$OKOt#m|YxTy8fRZLRat)XDVx27Z5^_+1 z>!JF$!5qI3UB>}#cIFLoF~B2((yhQUwDLcR zX|Z0j_%;rUWG`424LGr|CCi>9&FuA0Hc7YQLwWd{uJr)r@K9U&LxD0_2fH|2&uQvY zoTd`4UOk*}zLdNB%3umQk*d5_J$h`OJnHh5p|7?n2hi$|J3ea45+Pb>ExDuShOHpR+JW)Kw9DHQaVdQxwlM#^;k(RZ=)c zJq3Dy=&$VQu1^TEaZ6@S8EC~j*#>_ZX$!48CZ^kuB!xC^LgDM zz~0WFE(%!downFA?G1a!2yQJ?KJ>sh2bcBe$)=tq|> z%F`k*lAbv17d>zAVU3>v>XC3h*c|i~rN7ua&l=}OtaZs;6n2K2R*#k1=38qJ z6_ta%kN+krh(EPX^jXK5#)jT)5K&76S1BQSb^?NEZv#iNluia28x9q*Ms_ zs+cfvArS{Izs+F-yg+vk{NjbLbZZJ{iHpxT(&k`ec|0yMqW5-E65Ig zXvd}nduA|QDDYr*%e`*Fk^{Tg%#SWRh5 zcb%jGe6e@zNMOK{mU-xV>D6v(jn56Ek#dY)d8@0FwChJ8g0#srrQXB9DN#JIKG*mcE{3v>Ek6L4wo8n0RjpCGiW%!knkzTp6lF0Vm z6b=ri^BeKS=*1#zal;K9;|(Rm{hF|L1ClgRf-RW!fd;mly_F5Zej!W_&}A~+MI6oO z8io2XtgZECYV~-n0In0P`%Ct2HC#MEaU`vK6nza_}{&;Ir8AVuut=UY1{!tAJ{XBX+UKJxo z^Vh!j2Fqgk#krUGD&N;sE0=dnwb_%Hj=9C_k(QS!Pe>Dh$A+A&X!?{_BnZT*cEbZaK;*@MXIB@zoWNv~!_(X`aOie_ovq)~caW~k3Y#ez8 zWvd59(AdY`ACA7)-bmNr7D2EQ?16d$P-ZzIo9aY+p}ODeoUj|56xWH_)A+HD=w-2J zSy-}iP_aa5zd~R{U~P}|ZeUNoF_OmVEd)3mVO1KgSO-8fqE*0LNHN7HebOJMYGgt? zGhN|!qlj`u(&XgJd~IVh)Jt z^-T*VX6>G6L~$-@Vu>;?RL7ZmDK*Pw^{u0Ql+)|bBpp zuc_t3*|WO^2g#f-cIMO0$FJHjq_$d=Un04SDXU9`IQPbw6H%nRs?fF8W*tvrg! zn9vHXn-p053X7eN;I=A7T%?P5l<3*`T9JdV0KX&Uwec<1-KU-U>zUxL7`@>}F1<8S zp8yAuNNSUuauBXK+ja$#SsN}|sVZzHn< zM@~W)KNQgM;q-j;4pEHw2sYG`r$aI^w_|GJq{HMX^9zwrdH!iqNP-SU|`$i}!^TMjAh zXaUJi*qiaG-75jbjyG0DQohZ2y_GE8_YgQPE&JvGaMZmq=%M&_G1_WxnPfc`u3cx7 zp}CX(c5{wysR*;hbcL&7nB$KHX%?af!M)iaiu!6YmxhLhH23KLr8Yl1 zAKT2VdqaXt<863jj0)Pq#9^HKf38zCc7J~lA=eY2B%W_5^O}UK)PAGO>%i&1@$+_x zFXlViPF(J0+58?~H70dfDT9WK>l2{wR=N`YzweWOw)x?8{%6N8V7^>-XNIZX>jR5 zbU(_^qjLnG_yQ}rvuT|(N2Z99t@o7X+kZ|yE(}nZebTCEmxzXHXe3%KOONd#fmvhY zR5k&z2&y>T=ULxLD7?8l{wM4T>&b z%PoK)A=0b{`|K$5NgRrMbBW-y2WXehf%v1!4;Up72mKY>U8(L1>f;>5_k%WXq_tJ0 zC%_5BE}q-;4WrRofbJ7uq7|=-Ey+dYaH-F5q0j=v_1MtjeX+2j%;_)z!NfRfoG~O} z5@%=+%;REWs*~x@qE5njsQa_23X2f!0v{TUxht`E)^G&Mt~npZT=ZtXrGJ0J zTN=rLl!&WpH; z@6pdl?N3(H^m5gFdD94|+x1Q(qbr<7tk7ayI~8x8*_spm>z4ve>&>ghY&`rR16oE_ zhMh7pg_9~eCdD$g&xpo`M7aEi6uG08P1ZYUItfaWO^Qe%o%Z(?W~oW!46x8^UV{@F z+=0u(#+b9yxCxQQCWWuJK|}PR*ST?vnsRip<7#w4`d*EHd0!KE(Y4NL+xVNba)@A8 z@qt5Mi&{Tl*&?NdzCH3ywzDC#qoYvkAQyM50YO(xB>7=!n?zrK?5)5I!|lVOgj2KC z>*ld=-C%TUOPtX6dt`oF?W(M^`Z3HkDbj3C+S~e_uoV1mL@2*p&06;T32|V8x@(GCdGpgwXZS1pr?|= z!ll$Q#A;25cTzYGYf#ZWlh#KtJs5$ZWDA+d5S7B_XLS= zB^rk52yr}H^HS|_lCzJ!ofw0-Dd?Te@jU%{fI6olO%J+JiyC!_28@XEl|}P3y$X9+_ZL zPSUM7dRyBZ%cyLAH3x^YY*>KH2uEBVQR68!m;QMsgmkmewNYK{3h`-nTRj>N@c9OLtF zY97pmCXkwJ`SjN^83^^FfVWdnZ}5@|4eAqbkig%@r@b^t{$$xf-567=+63B6$cSM5 zxY>?an@3<5X)$x3T;XW8hh?29a{^_ZE!5!S!s2` zh@$#M-}HT4x^3UZ06T?l1(uTE7z?|cGIgDuW8K2gFf}CuG#O{QDin2^gzyQ*J0u$( zQM9@!MJ`ha=iG&F`?TexzVt8Y^0ZODoaI^2=Z>Sl9+kr(tLA_WKKdQ6)okCxB?UNC z%JGtJR*APs=yrn>vS;LPfkZ=mY>B&zpb11Dqb;V|K*Odp!iWi#K(}?NVNkyMr09Bb ztIG)OZza?`wNm|#@yolbo$_zW~FD1dpGpM zq4+6zeI9`|)&Y=FQo6ers=RzDbmlcK^%zZprsVM%7C!peQ^h4wS!YL4IZ~GR5BP@Ol3!a8U4yB6JiI1L$DZz~gCQM~tvQhk|u9&7#RjCE*)X#u*KQP>T zM6`{X7!5rWZCoENMyDG626^E-M0O{e8L@mRCytHKz& zpP#C4>BOQPx!dLW$pwrUzm6k1liO_5QYBJVl=8!7w+RRpz69SL*U2mQl#Dart0d^+ zaQD8}oI4aY}~^N5ZfizKwl=(qHm{uM!ziJ27fKb_4w50{6zDat(5p8^Q9i6uPbu-UwoE zG>i?Nz!3&{_PL8`F6^#EQ-EY=0&#@}iD*I)07&7siS^KrAc%EQT}kHjfBnq0HH5k3 zUo|rHUaYfeNOvk zAG48*#=b?Jnctnso!Q^5nSb@i8g>6VNrur~i+0gJ=9a<6VeehciVtTqRqCC$!peyN z|G~KF825zwl4_Vq&?v`~;x6ox3DTz9v|mT4SmXOudDyYF&;WP*+Wb%a>U~ z8IFgtZ}=FnJRc539}c&uQ_#w%sM@P}=AF zuD9q#BzIOmx)I^cteLI2FpB=Q-guxZYJn+_>m1q=4K>D3?RjTenP*ze59H2d_@1{K zXC2URj7VT1s0a;AFQZ=Z@=3dwad=rJZGQwZ+ zCWFUpmPHbwavj>`(*^)NEvLw99PLvd4E}JGX)mh6*dR57;Xo2JsVwXQY35cNeB>up zEn^|lc;(jYdeJa~q)rCeFWnVZ=;wUoL06U|3 zPhq4HxzErkz{SG`1x(4(XtG7ZN>~*4K@EskOj?l1mcw!xC&85)&Dw5$y?q5amGI z>ot$~KfiQA#Q4MZ>>`>LXKc-ep&*6YC2(SJfWDJ za{{&FWDnX{sEwvOv1=hr&wJC0GFj!qhx)Yg(Kz1_y+s24gRo zbdg2{P+EZ?2>j>4U4U@+2%3J!ehcDfkEvu?{Z}vZ+7{gx(an`^xUq=(Tc%m6`MRJ} zD)^*v*N#j8db|A3p`}A^Lz06yvI~>=ky>m~q3$Ns3cLT1c=&qs-COL|~FR|y%Vw>myJItHF z^k8f}D3x!Kqu$3=L+_sBaxWyd9fqG2LO0?=W6D%C4R87Ioc`!%-)1_ zH=iZ{B8Zq8i1yx3Y&80G?hV%ZK$CcZ6Tb?z7;OErWE zToz(FpmrDGU8J zk<_7ZU|$H?!6&|_NoSMZ`k*Z}y3 z*?s^^1&;;Wrrizm0)DV4Z?J0d+t%b{6*7SFdM%V>_Z>7Rn^^Sz5AFy-5Tz0|`4*B0D2~pdi2` z#7@h>JE>t;y=YdvQ&-(Y;36`#T6R8dhOb{P9Cl2?y^Y%tW3m)Sv`2fQ`ox>y5j?Yj8GjM2O|45klTXD5oFGcez&@sr}SjOo(qI zSW}GYlF7Qnk%9zQP5Hp$P&TH@Js<7^&#aE&q6|S3Ec-HxK(Uz|L&L{T*$?r%z>j&f zKF)4;Y9zVubBrMAwhf{MmD-z3EYw(Phr;bx%?j0b)~v5!9Q+n+u#cs{3unsu(OGlE zRUkP4XkwO5h6)9db6Cs>f~xHAXF^P~05)jCnEjro0QS6@t(#(H4c8WGhMuE`IgH|L zE(JsEU}XT{_~jQO>L0UoyA#L6XtAy$pL2`lsY^{UJC`}T14a2HMH4UleE9UcbhB#^ zefb$d6DJ_EldYDbcSs2CBVxQkO-u2%AZmU00NTD4^5b0l0lUcYU+L5C;M&5R*F@Jt7g+9%;uiGD;LXmm%~!ai_*W3Po{x zA5s05&^T(KE!xmTEqHIMC$(F! zOCFO-K~#jwhIG<9o96jbhg^zt#i)%Z^`!p%}{kl0w1Un;B z1+gv#i0U5%ggFFwuUasl03s{<66-|u@s}NmAx{AN^F-h*X$?k5xtJj>s(M(j>c7f> z**yHatUo2fF|Kyv{%f&+(|Q5GJJcTq`uzU}vi<`R8#&NP=x&Ty$=|E~=K%VD0M>ti zeq;G>*2D;R7dC!5|2Ap^6}THnbjf01E?t zY1+7#7H<7+N}DWj7p{gJ&({5+qi8)Vb2W5j!4wUj8@Q8AN^f1(@ReK~KQpHArkULT zlJLiLe9Z!>Knzsh7VAO~T5V&oXTtV#bgTh$n}^G&N$fv^2#dd}X|UXe^Nkt@#Yv<9 zQFYRbHB^b0=d+BLYy^>$uO2{CZ4ok|28@svg)GNZJd(>`0!*18WWDjGD`x&SP6|zO{e_r`B6eW=iBwJk2HDc^AzvTSJ+{xQZ+Ov3e~5Me zQ>+(^bDRcLFVt?1{FH;`$;EYrbSi;FIvEiP*?~JQehR9cm)`TJ%I&9(<1|zj_77x+ zkTy?v%l-Hi>Q72a(8d6&TdD!bKZo&LjLkL3P^wWrZ(KRu=tfcL%Y z;`@(#BD{kwyb})SNj!$MSe4q0Qs3>%0KY?sL9Mfy7KvvlQoxR_qmi9JKP_zm=_5)P zP9Iz?=4ZUzC-0j{C?rq!m3)J<2T`N`pvFn8o?%6+e5paIKR_0+J(?JJ+81c?_FJT& zoqBO3Cg4>K*;!_w^LiR{apGtedIBIe@mss)%7}i;g?g78-hNq2$yU}2eDpzMm~B4y zSSNi+jKV34d{5;Ouwt0v6g>}~?naf1RnkrO_VOCdA8-eQe(FQ%g5JyG|p7n_-)0&67 z+E}|+lt~d51w-`0)=6%t8tA)3b>hxQluT~`om&!>s0jwiwXGm|c;L%WTDq{d}xehlWS%{6K3#u2bAb!B#!gbk~>vfk{ z_NjJO{W$YfSAnuP*s%i(COMvt__Y4CEReZ}L=apozK-3wR4#}!%v2-2her)^Nyn&G|;`s$AvSQ}aGBjc4fv|)jC$3%P0YMT@IO{9Eu5!X| zgrQwNZ?B#wz^F*!bn2#d80@N+o&5lOF{grNC7)(HC0H0M6p1Nt9VEDeUNj zPsjPPNZXsLsbG?JB9>{DqYX`p)t0nwqAhn9Q`Ty$C}@BQMRwH@8i&s&E7lB_Oo6=c z^XXHxC@1gZycfVLT+wj#~ZX!D_V+Cq8)5Y2fj6gX$D4i zRfz8I?7@eQhH01Vy0qWn9F(@0v3&FoY zGDHd2Z~`uj-pxp5w1#S*p3Y(!>2t${t3vEkaO?TlpOe!px}H~!Q! zR4@Zk=p%{ELt|i9xP94f(I6}tM=hl2YY%+ULfVTPtqzqZjt`jl^i`dtX@z(;PjeDc zDrS3}iR@G7auqRS^&|9;=LUBgl8R*^%nL$_+51Rw{e5OV~?h^3Ll|0exW7^gida!3|16B~g6f0G))gGRQBQy=umXc1a-GIu>Z+ zAWULBf6Yk2gby}53z@0XSOb}7`Wy{(hX`Nlb``ZKQf;@v=iXRM;)oV%ZCDRNN_7N; zjmns^+$Gr}i4AM7-jq*;#XT=u@R^%JgIC(i>YTtS(&bxV)=Qc(3T8q+E&=r+rH&h| z11ssQh3)o~dr^?c-m0iNt>)684p%}mDaXAHt6g>cA``Ch!=BOGP!HWcxukcXI zXq=`EVin+$ae@%S3@HhV>lox{l5Fh29%AQ_wt^4xiK91P+XaB%P%k^AV{NbaR|C9# z!u%}%t;zq_EbY_e^{;TkFV>&f0ut*9!2RR*NzBhbpa=W$YyRgiAjFTKHGzQxAfBH@ zLxND41&K*mgkD2okU}%*qqDNxu_^fceDDko1_tx|;JF4Zp6LUdwtJtrtqGhY)q7Qr zaH;ti7~=U(WP{K~y-mQo!@NLX-bWxJa~+5dkwag>ff}}1h^3Z4j6t*yEJ{I8O%Z_b z@fdxV43cgTL%AaOYc}s=ySS}kxmvX|oZyZFvtOPMU^Il(q5UGG$|I+A+t1NxrL+y6 zP@=_*rWyMQa9%Ld68XA>*pY45d}J!Mh*i!sW0X7X-^%84>r1ux+_I9f{JSSB^7n!f zdRv3oRGfeB#D*na-POMKj=ePZkQch$BizfmR6Cn|0+7vJbKI+06iKl?0h+&8Wf!_U zif_+ceH$lC?!6-NvOj%C#P0RTc)>5AcZQqUAuG$a)L7YWoi3*Pe%Yl?^bo42tg@A$ z=e0o5(rlG>L$SpN3q8EcCF z1(UCr_xC#r1x^n=-ukRt*S1BoLFi2%m#1%OuGuZllsrom0~O>dzb(Ekq)}cIG||*- z*O;2vf$uPp;Zb`OO~B8C@U}ntqwhLu?|O-@W{w&TXJv(_x^5OLg+#Wp_HvF|IM}Q) zaH430l#KGMiv72$)(XB$6m|%+mlltI^9sI1S2H!Vz}+(~GYDBwhF11WQ6{6&0wJ^@ zjVgWRQCmnI#&zPjF3ZE^tZ0})Kb$SgU05uju$DiTTRWYcPca#Aw#e?9(x_`J5GJr$ zWoJ{3n_PfH`BXUhscts!G3@6peo;`%*=~5hK*d7TmDskyNXh zIKK=z;$hEVtBX5;xUS*iO$@a#M-x*Ljbc@cM}&e(5X}e@nAw&a&JOiDq#vSXbtBm& zQKyV^^Re6b!CrG0RDYJ%3>p>>{lH5B&wz1b!5+#gpQi~#-I)BLcS(N!D()-Ujl$^ z=Tl0qXg#yfK7eVoJ4w`gMG&0^x$(p8-H9X(d9{aA9T`kUT9R3I|Jmi>+2lVh|4RT1 zzm0_Dza?^{h5rdKC{^?P5^u!6dA9d`L#|`|ccUoFWlhrtUdyG#AA!yrW@S9>CDr@; z%V@{1;-?-HKLSaHdv-UclfBaeIL92&au1c_)`|wgXWO zKKmb?%DFj|>5D!|C^|{V^#Les5&mqyY#zoYLKwHOH|iNo57LOB`_X+{shj@&{Qn0b<2KxENdb;+1*u(^f1hdZ|%8mgn1mlgJf)ZMnjyafFIlPkdV+ouphhf zKmPL(I4TJv$f5W?qb+2MmtpHiG0lr*|Pqoa!gl_p$tv&h(1cJbl`bcNDq5CAzY z`i^XZFyu-immhUM`d?(SNsm5VT;G9oj*%9v2?F0Q9a#%D>*c*!_TFzaNY{x4^p%k* z8L|_9!Eg5xopTJA9*koIz(FL8cDrXh$e*D}<)A8Q(l^dMgE(g@gZmM;qGkbjBxEXU+${O zy6^N4^!^Y!cG#a0G(}ap3xn#70T9PrUb^kEis`QzA7?n*XeK`0w{tF$RN+(}`O1TY zb_>QAP#qNsP?dNR78`P=crM5&YJ1N=?+JlJFXpd;FBqDc*>m~i>|hb8)Y6}BS_}2A ziCoKqomfqDb+gw?POxDm4W0qWdY98XVFPaMv1ANl<P#eI534kY#f3co086vjTr)=c_*H;JXbYzgh*?^s zRFKI5uzVq#{yK)Sgbn^pXy3d(moBAH2=OC`f4*-O4YnElG-BX}uic#+8_vhuL8O%} z(BRYV>$qUN$~_SgU$R?qB~sMxeh!#+Q=vGA32S>SPUKdgW9yPg^@e>nZx4+u40^&o zl9@>b&gw_0t1iD)mkTW!_4J@fa5gqtYh+8i_y82q$$-z1s?$v%5gkEOpq#=OYChOY zROnOC*u+=-+0XF)F)h@+w@g9320*pma24xNu!6i+NS5)l(nZ7GWi~U^oE$APcddX7 zVn50R$^eVT%z41DP^00z)OKb-y&rj`TSs-nmFYVh;c_um@dBk@sJ4f{uO$eFG^uKsvnPci4nq+);O-3$R`yq@pv%|< z_DIE0e#uUAkAMci0s$L9IM4WueRH#TCPW0qfFkaKiXP%FG7t*QGRa>(=6E2F^-WvW{;}L+|Qy!(ROTc?0(kh`G`F zf6tj4Ca`A~_nOc-NRK*SnW`0rJUP(Ucu4s6Q_^Ouj4+ zO}ap$i%{gEZna**XqYwx+EuE)TB`JHXgZ)FFH2z2v>DZG^J^W2G!HB%kq^bl+Oq!6 zdwrbQzqnhgDh5v*xj-vntYOlovh^W*z55^aIdA?S^*Kynq~kdrGyb(Y1%f}nAoU|2 zKPNym6jWwN52dUON6T0)xP!8i;At6s-+>7YQ<87T1y1AYefmQw3fc~_x7Ii{_}g^ zd(NEinK|>EXP$XJ-Mc{%ges>lEKzi+lDp zIru8Q%8G%aI`hnvr)$Hs=00Gz=BwUQZ>sERx(Rnbb*p)x(v$}nvp)7EaToR|-lJmU zbb{KPgtFLw3PbmbOERxjRyv4~$?(F!4Pvf=)#DAvFY)cTGl`C+&8c_Yi8)e;Wv@G@ zo7IDtng>><@IlMT0@#~!3F@r(OVjG&VHp8}*N6u<8=d`(2BhGK)k(tKnAN8epl-gV z$FA2P?!LcIr8uoqZ*%93du4{VfVQL5L1z}b0U|d(ttyLV>CLTI04KeTkwdrY!JmStfI6LYOZ^nRZ=NKz1ZzazLWs^&K6M{rV1C1*y)-TAb(inLGMv+o}(sWVH8kA@l#%T471#2UvN|}#hvn2NYutDu^21Bv_wiE z6_;INhb9*GZ?J&+GqwXS&9{__vsDL9{Gr_)UM+;`PDt>{apgs;_5WF_B(B$*A82`# zuRB`$g&8bT1v@KtL}6A>OhoSrNR*T^P&3|GZSkE=d{t$qe`#N&G{cm)9ZXHtvv+L_ zz?8o?JCUv05_`6E-if`WAyCR{{36@C;D*}@N6i{;JzUbl zNx@KaaoXLLiyyQHpfd)VZIv`%D3U}-J@o1|IS=a$uLa3CcyH{H#>nKWNCN2HE5clQ zP*0?1s=wsOHm-8?z% zX)8q3Ux0NP)W_J(*y>5T5*S%;Hp*!ft21+mEb`YBo)`7|U}UYK&EUq86Vx zac?U(CdlvauGlX%1^s_n^d#*}RxP3T%h4K5%S6w*tg3fXE zb*sF?8Sl*fQ&@Z;E?szU`tHM0X3W~XuG^-gc#l_U5ai?o{{dSalPW`WtHVBzF$2z>abL|?jIPZBB;{#*ygqw@ zZ03-#_Jz$(z4ku)(Nel>Gl%CRzWgCzjpMv)3VbpJWs(+7ojCpyqQj`&ibJ3An`osa1}%i0e+0H^W&Vv()|{u_VWl!&q|q##mML z2SWR48jTCKsP()mr{LMVe(AnrtKxFUeGjSQ2>w^J#==~4(%bE!V4Z!`qry6DZwvm_ zLwWOJoRV1v%qX>9A`0M#1N1&XS)Ca2s8@S!=x10Qug@CKq7pq(*^Y}v`zGI7=&(Nk ztApca1%Igp!3n>RRw()HuGm)&K-hJ7#k(N#0fjs9O1hzJ zc`LQSKVV}psG`zYunQc4a;?PQY5Bc~1W5|Lu#-`vqq`_# z<_sUcq`~T{x~1>3VrS|{gz0&9Q&n54RRCD4layN#MVHEu-A>JZZQjptuBzRFESB)l z_KF+KuOyfxb@(lOh?{~06SXa)Y_e-!`h0oZ)AvRpOF6tSs+LeQZoSl4w+^Vjq7iIc z1+C+)skJlClHbyGBC6ZXqriq0Q@bdi^677Y{YvGML85e}!dv~T4Y7ftowBDYW}aDP z&g7WzX(7qIba{i~^XJbpO;0N+&^j@Y>F)H~w%J)Xx{2#*xFGF!M6`+Fa<$>@VE-@j z`KL6z+RlF+ESsbk1O|+AvabxbJNOwv>|A}+CB~M%0E3%yDVdEcvS^~aY6!HFMS*yt z)yePtR8`Z-E2}`<5D)A|8F^z#vp`AQPMb=?`q9DMuZ0Y(rDat&+Hb!2A{FTQ@>W=e zv?X%s*$lhAu=4O5a?FY}u1f-(i}l*-MvKwD;wA?@;!@wA?0%lnjTX>&rAYpvNG5%$ zN-jbkw<02#NyooIEyIIN*FnHBD#|P`OxkSl(;nwZcd%=Arfh3}ynp*3%7O`glWX6g ztJ_8)eOB&|`eQdLDTuYZM9U5KK-xx=sYtkBKRE(g%PL}*{%IsbUB1Hpg)a4`M-5&iNX#ls56{=aK~$`SI)ZRH&Z zu#ka7P?h{$Zh2}5p#C@fW6I`^u)P@7t2+QOp;c5lST_2+b_ibcSTIAv4V5*vXkLy_ zBH))dHv{NEw3im3w%o{26L}>pAFTM2WUK)g%w=MtcNTnG#zt97J%Z3Mg;4X&{qJn( zwXecD$|+S2KD(5wCS9}UyA-|06w);IqMo|D2JH7fTHIP@nZ`WWEtCoV+|`?0B~;an zL=A_^8Lw$lOX3c0R=AxP(4eq3RBwV;RNU0ay!8yjtv$}$Q?XZkEwu+twf9?%VAHriUV$2rs8g|8ULU;O-gseeAe$cX4>VoDJWu-M) zIY-JS*fnqGw%~NesmC2CyIG={UlqYAi?>`;w`uXS{NfAoZ6+e9ZZ32uF~EP`YsU-M zWOI+WqA{{(3A|oJuEnVoTDJK0%0}MFXVqy$rx}d+o?}doOx(y)cDY&m&Sz49>`Z$% zPR0}98?HFL#<-T?ghg5UXv-;c;!>?IKfG_JL0-?a@E*n$_q*b=2~e(WoG?Tb`zJk5 vmb&wnI#!oB?}7wQ$hP>vM!`n1iX literal 0 HcmV?d00001 From 2b5517fc7f75ef710a846834cde64c9a2fd52502 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 12:41:58 +0100 Subject: [PATCH 050/130] Refactor registration logic; move to model --- .../com_joomlaupdate/services/provider.php | 4 +- .../src/Controller/UpdateController.php | 20 ++ .../src/Extension/JoomlaupdateComponent.php | 196 ------------------ .../src/Model/UpdateModel.php | 112 ++++++++++ .../en-GB/plg_quickicon_autoupdate.ini | 4 +- .../src/Controller/BaseController.php | 46 ++++ .../src/Controller/HealthcheckController.php | 35 +--- .../src/Controller/UpdatesController.php | 37 +--- index.php | 5 +- installation/sql/mysql/base.sql | 2 +- installation/sql/postgresql/base.sql | 2 +- .../src/Config/ConfigServiceInterface.php | 34 --- libraries/src/Config/ConfigServiceTrait.php | 36 ---- .../src/Extension/Joomlaupdate.php | 95 ++++++++- 14 files changed, 280 insertions(+), 348 deletions(-) delete mode 100644 administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php create mode 100644 api/components/com_joomlaupdate/src/Controller/BaseController.php delete mode 100644 libraries/src/Config/ConfigServiceInterface.php delete mode 100644 libraries/src/Config/ConfigServiceTrait.php diff --git a/administrator/components/com_joomlaupdate/services/provider.php b/administrator/components/com_joomlaupdate/services/provider.php index ae4bb2ddec2f4..b55a04a784520 100644 --- a/administrator/components/com_joomlaupdate/services/provider.php +++ b/administrator/components/com_joomlaupdate/services/provider.php @@ -12,10 +12,10 @@ use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface; use Joomla\CMS\Extension\ComponentInterface; +use Joomla\CMS\Extension\MVCComponent; use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory; use Joomla\CMS\Extension\Service\Provider\MVCFactory; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; -use Joomla\Component\Joomlaupdate\Administrator\Extension\JoomlaupdateComponent; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; @@ -42,7 +42,7 @@ public function register(Container $container) $container->set( ComponentInterface::class, function (Container $container) { - $component = new JoomlaupdateComponent($container->get(ComponentDispatcherFactoryInterface::class)); + $component = new MVCComponent($container->get(ComponentDispatcherFactoryInterface::class)); $component->setMVCFactory($container->get(MVCFactoryInterface::class)); diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 4d3b5ee52af57..f7d707b8978c4 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -18,6 +18,7 @@ use Joomla\CMS\MVC\Controller\BaseController; use Joomla\CMS\Response\JsonResponse; use Joomla\CMS\Session\Session; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; // phpcs:disable PSR1.Files.SideEffects @@ -732,6 +733,25 @@ public function healthstatus() $params = ComponentHelper::getParams('com_joomlaupdate'); + // Edge case: the current state requires the registration, i.e. because it's a new installation + $registrationState = AutoupdateRegisterState::tryFrom($params->get('autoupdate_status', '')); + + if ($registrationState === AutoupdateRegisterState::Subscribe) { + /** @var UpdateModel $model */ + $model = $this->getModel('Update'); + $model->changeAutoUpdateRegistration($registrationState); + + $result = [ + 'active' => true, + 'healthy' => true + ]; + + echo json_encode($result); + + $this->app->close(); + } + + // Default case: connection already active, check date $lastCheck = date_create_from_format('Y-m-d H:i:s', $params->get('update_last_check', '')); $result = [ diff --git a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php b/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php deleted file mode 100644 index ddee8c1f60dc3..0000000000000 --- a/administrator/components/com_joomlaupdate/src/Extension/JoomlaupdateComponent.php +++ /dev/null @@ -1,196 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -namespace Joomla\Component\Joomlaupdate\Administrator\Extension; - -use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Config\ConfigServiceInterface; -use Joomla\CMS\Config\ConfigServiceTrait; -use Joomla\CMS\Extension\MVCComponent; -use Joomla\CMS\Factory; -use Joomla\CMS\Form\Form; -use Joomla\CMS\Http\HttpFactory; -use Joomla\CMS\Language\Text; -use Joomla\CMS\Uri\Uri; -use Joomla\CMS\User\UserHelper; -use Joomla\CMS\Version; -use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; -use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateState; -use Joomla\Registry\Registry; - -// phpcs:disable PSR1.Files.SideEffects -\defined('_JEXEC') or die; -// phpcs:enable PSR1.Files.SideEffects - -/** - * Component class for com_config - * - * @since __DEPLOY_VERSION__ - */ -class JoomlaupdateComponent extends MVCComponent implements ConfigServiceInterface -{ - use ConfigServiceTrait; - - private const autoupdateUrl = 'https://autoupdate.joomla.org/api/v1'; - - /** - * Prepares the config form - * - * @param Form $form The form to change - * @param array|object $data The form data - * - * @return void - * - * @since __DEPLOY_VERSION__ - */ - public function prepareForm(Form $form, $data): void - { - if ($form->getName() !== 'com_config.component') { - return; - } - - // If we want automated updates, check if we have an old key to use otherwise generate a new one - $config = ComponentHelper::getParams('com_joomlaupdate'); - - $token = $config->get('update_token'); - - if (empty($token)) { - $token = UserHelper::genRandomPassword(40); - } - - $form->setFieldAttribute('update_token', 'default', $token); - - $data['update_token'] = $token; - - // Handle automated updates when form is submitted (but before it's saved) - $input = Factory::getApplication()->getInput(); - - if ($input->getMethod() === 'POST') { - $dispatcher = Factory::getApplication()->getDispatcher(); - $dispatcher->addListener('onExtensionBeforeSave', [$this, 'onExtensionBeforeSave']); - $dispatcher->addListener('onExtensionAfterSave', [$this, 'onExtensionAfterSave']); - } - } - - /** - * Handles subscribe or unsubscribe from automated updates - * - * @param $event - * @return void - * @throws \Exception - */ - public function onExtensionBeforeSave(\Joomla\CMS\Event\Model\BeforeSaveEvent $event) - { - $context = $event->getArgument('context'); - $table = $event->getArgument('subject'); - - if ($context !== 'com_config.component') { - return; - } - - $data = new Registry($table->params); - - $autoupdateStatus = (int)$data->get('autoupdate'); - $autoupdateRegisterStatus = (int)$data->get('autoupdate_status'); - if ($data->get('updatesource') !== 'default' || $data->get('minimum_stability') !== '4') { - // If we are not using Joomla Update Server or not using Stable Version disable the autoupdate - if ($autoupdateRegisterStatus !== AutoupdateRegisterState::Unsubscribed->value) { - $data->set('autoupdate_status', AutoupdateRegisterState::Unsubscribe->value); - } - } elseif ($autoupdateStatus === AutoupdateState::Enabled->value) { - // If autoupdate is enabled and we are not subscribed force subscription process - if ($autoupdateRegisterStatus !== AutoupdateRegisterState::Subscribed->value) { - $data->set('autoupdate_status', AutoupdateRegisterState::Subscribe->value); - } - } elseif ($autoupdateRegisterStatus !== AutoupdateRegisterState::Unsubscribed->value) { - // If autoupdate is disabled and we are not unsubscribed force unsubscription process - $data->set('autoupdate_status', AutoupdateRegisterState::Unsubscribe->value); - } - $table->params = $data->toString(); - } - - public function onExtensionAfterSave(\Joomla\CMS\Event\Model\AfterSaveEvent $event) - { - $context = $event->getArgument('context'); - $table = $event->getArgument('subject'); - - if ($context !== 'com_config.component') { - return; - } - - $data = new Registry($table->params); - - if (empty($data->get('update_token'))) { - return; - } - - $autoupdateRegisterStatus = AutoupdateRegisterState::from((int)$data->get('autoupdate_status')); - // Check if action is required - if ($autoupdateRegisterStatus === AutoupdateRegisterState::Unsubscribed - || $autoupdateRegisterStatus === AutoupdateRegisterState::Subscribed - ) { - return; - } - - $http = HttpFactory::getHttp(); - - $url = self::autoupdateUrl; - - if ($autoupdateRegisterStatus === AutoupdateRegisterState::Subscribe) { - $url .= '/register'; - } else { - $url .= '/delete'; - } - - $requestData = [ - 'url' => Uri::root(), - 'key' => $data->get('update_token'), - ]; - - // JHttp transport throws an exception when there's no response. - try { - $response = $http->post($url, json_encode($requestData), [ - 'Accept' => 'application/json', - 'Content-Type' => 'application/json', - ], 20); - } catch (\RuntimeException $e) { - $response = null; - Factory::getApplication()->enqueueMessage($e->getMessage(), 'error'); - } - - if ($response->getStatusCode() === 200) { - $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS'; - $data->set('autoupdate_status', AutoupdateRegisterState::Subscribed->value); - - if ($autoupdateRegisterStatus === AutoupdateRegisterState::Unsubscribe) { - $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS'; - $data->set('autoupdate_status', AutoupdateRegisterState::Unsubscribed->value); - } - - $table->params = $data->toString(); - - if (!$table->store()) { - throw new \RuntimeException($table->getError()); - } - - Factory::getApplication()->enqueueMessage(Text::_($message), 'info'); - - return; - } - - $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR'; - if ($autoupdateRegisterStatus === AutoupdateRegisterState::Unsubscribe) { - $message = 'COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR'; - } - - $result = json_decode((string)$response->getBody(), true); - Factory::getApplication()->enqueueMessage(Text::sprintf($message, $result['message'], $result['status']), 'error'); - } -} diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index 68984a0677335..4598d6223c2d5 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -26,11 +26,14 @@ use Joomla\CMS\MVC\Model\BaseDatabaseModel; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Table\Extension; +use Joomla\CMS\Table\Table; use Joomla\CMS\Table\Tuf as TufMetadata; use Joomla\CMS\Updater\Update; use Joomla\CMS\Updater\Updater; +use Joomla\CMS\Uri\Uri; use Joomla\CMS\User\UserHelper; use Joomla\CMS\Version; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; use Joomla\Database\ParameterType; use Joomla\Filesystem\Exception\FilesystemException; use Joomla\Filesystem\File; @@ -48,6 +51,8 @@ */ class UpdateModel extends BaseDatabaseModel { + private const AUTOUPDATE_URL = 'https://autoupdate.joomla.org/api/v1'; + /** * @var array $updateInformation null * Holds the update information evaluated in getUpdateInformation. @@ -528,6 +533,113 @@ public function prepareAutoUpdate(string $targetVersion): array ]; } + /** + * Change the registration state of a site in the update service + * + * @return bool + * + * @since __DEPLOY_VERSION__ + */ + public function changeAutoUpdateRegistration(AutoupdateRegisterState $targetState) + { + // Prepare connection + $http = HttpFactory::getHttp(); + + $url = self::AUTOUPDATE_URL; + $url .= ($targetState === AutoupdateRegisterState::Subscribe) ? '/register' : '/delete'; + + $requestData = [ + 'url' => Uri::root(), + 'key' => $this->getAutoUpdateToken() + ]; + + // JHttp transport throws an exception when there's no response. + try { + $response = $http->post($url, json_encode($requestData), [ + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ], 20); + } catch (\RuntimeException $e) { + Factory::getApplication()->enqueueMessage($e->getMessage(), 'error'); + + return false; + } + + // Decode response + $result = json_decode((string)$response->getBody(), true); + + // Handle non-success response + if ($response->getStatusCode() !== 200) { + Factory::getApplication()->enqueueMessage( + Text::sprintf( + 'COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR', + $result['message'], + $result['status'] + ), + 'error' + ); + + return false; + } + + // Get extension row + $extension = new Extension($this->getDatabase()); + $extensionId = $extension->find(['element' => 'com_joomlaupdate']); + $extension->load($extensionId); + + // Set new update registration state + $params = new Registry($extension->params); + $params->set( + 'autoupdate_status', + ($targetState === AutoupdateRegisterState::Subscribe) + ? AutoupdateRegisterState::Subscribed + : AutoupdateRegisterState::Unsubscribed + ); + + $extension->params = $params->toString(); + + if (!$extension->store()) { + throw new \RuntimeException($extension->getError()); + } + + return true; + } + + /** + * Get the current autoupdate token, set one if none is set + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + protected function getAutoUpdateToken(): string + { + // Get extension row + $extension = new Extension($this->getDatabase()); + $extensionId = $extension->find(['element' => 'com_joomlaupdate']); + $extension->load($extensionId); + + $params = new Registry($extension->params); + + if ($params->get('update_token')) { + return $params->get('update_token'); + } + + // Set new token + $params->set( + 'update_token', + UserHelper::genRandomPassword(40) + ); + + $extension->params = $params->toString(); + + if (!$extension->store()) { + throw new \RuntimeException($extension->getError()); + } + + return $params->get('update_token'); + } + /** * Return the result of the checksum of a package with the SHA256/SHA384/SHA512 tags in the update server manifest * diff --git a/administrator/language/en-GB/plg_quickicon_autoupdate.ini b/administrator/language/en-GB/plg_quickicon_autoupdate.ini index 8eae5aa40a6b3..e012f1bbd4a95 100644 --- a/administrator/language/en-GB/plg_quickicon_autoupdate.ini +++ b/administrator/language/en-GB/plg_quickicon_autoupdate.ini @@ -9,7 +9,7 @@ PLG_QUICKICON_AUTOUPDATE_DISABLED="Automated Updates are disabled." PLG_QUICKICON_AUTOUPDATE_ERROR="Unknown Health status …" PLG_QUICKICON_AUTOUPDATE_GROUP_DESC="The group of this plugin (this value is compared with the group value used in Quick Icons modules to inject icons)." PLG_QUICKICON_AUTOUPDATE_GROUP_LABEL="Group" -PLG_QUICKICON_AUTOUPDATE_OK="Automates Updates working." -PLG_QUICKICON_AUTOUPDATE_OUTDATED="Automates Updates Connection broken." +PLG_QUICKICON_AUTOUPDATE_OK="Automated Updates working." +PLG_QUICKICON_AUTOUPDATE_OUTDATED="Automated Updates connection broken." PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of auto updates and notifies you when you visit the Home Dashboard page." diff --git a/api/components/com_joomlaupdate/src/Controller/BaseController.php b/api/components/com_joomlaupdate/src/Controller/BaseController.php new file mode 100644 index 0000000000000..23306f410cb4c --- /dev/null +++ b/api/components/com_joomlaupdate/src/Controller/BaseController.php @@ -0,0 +1,46 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Api\Controller; + +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\MVC\Controller\ApiController; +use Tobscure\JsonApi\Exception\InvalidParameterException; + +abstract class BaseController extends ApiController +{ + /** + * Validate if the update token is correct and auto update is enabled + * + * @return void + * + * @since __DEPLOY_VERSION__ + * + * @throws \Exception + */ + protected function validateUpdateToken(): void + { + $config = ComponentHelper::getParams('com_joomlaupdate'); + + if ($config->get('updatesource') !== 'default' || (int) $config->get('minimum_stability') !== 4 || !$config->get('autoupdate')) { + throw new \RuntimeException('Auto update is disabled', 404); + } + + $token = $this->input->server->get('HTTP_X_JUPDATE_TOKEN', '', 'STRING'); + + if (empty($token)) { + throw new InvalidParameterException('Token is required', 403, null, 'token'); + } + + if ($config->get('update_token') !== $token) { + throw new InvalidParameterException('Invalid token', 403, null, 'token'); + } + } +} diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index d4cebbcb1578c..cb7eecdc77b35 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -4,17 +4,14 @@ * @package Joomla.API * @subpackage com_joomlaupdate * - * @copyright (C) 2024 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Joomlaupdate\Api\Controller; -use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Language\Text; -use Joomla\CMS\MVC\Controller\ApiController; use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; -use Tobscure\JsonApi\Exception\InvalidParameterException; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -25,7 +22,7 @@ * * @since __DEPLOY_VERSION__ */ -class HealthcheckController extends ApiController +class HealthcheckController extends BaseController { /** * The content type of the item. @@ -164,32 +161,4 @@ protected function allowAdd($data = []) { return false; } - - /** - * Validate if the update token is correct and auto update is enabled - * - * @return void - * - * @since __DEPLOY_VERSION__ - * - * @throws Exception - */ - protected function validateUpdateToken(): void - { - $config = ComponentHelper::getParams('com_joomlaupdate'); - - if ($config->get('updatesource') !== 'default' || (int) $config->get('minimum_stability') !== 4 || !$config->get('autoupdate')) { - throw new \RuntimeException('Auto update is disabled', 404); - } - - $token = $this->input->server->get('HTTP_X_JUPDATE_TOKEN', '', 'STRING'); - - if (empty($token)) { - throw new InvalidParameterException('Token is required', 403, null, 'token'); - } - - if ($config->get('update_token') !== $token) { - throw new InvalidParameterException('Invalid token', 403, null, 'token'); - } - } } diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php index 85109237a3ca4..83c88279b9014 100644 --- a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -4,28 +4,25 @@ * @package Joomla.API * @subpackage com_joomlaupdate * - * @copyright (C) 2024 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Component\Joomlaupdate\Api\Controller; -use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Language\Text; -use Joomla\CMS\MVC\Controller\ApiController; use Joomla\Component\Joomlaupdate\Api\View\Updates\JsonapiView; -use Tobscure\JsonApi\Exception\InvalidParameterException; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** - * The healthcheck controller + * The updates controller * * @since __DEPLOY_VERSION__ */ -class UpdatesController extends ApiController +class UpdatesController extends BaseController { /** * The content type of the item. @@ -219,32 +216,4 @@ protected function allowAdd($data = []) { return false; } - - /** - * Validate if the update token is correct and auto update is enabled - * - * @return void - * - * @since __DEPLOY_VERSION__ - * - * @throws Exception - */ - protected function validateUpdateToken(): void - { - $config = ComponentHelper::getParams('com_joomlaupdate'); - - if ($config->get('updatesource') !== 'default' || (int) $config->get('minimum_stability') !== 4 || !$config->get('autoupdate')) { - throw new \RuntimeException('Auto update is disabled', 404); - } - - $token = $this->input->server->get('HTTP_X_JUPDATE_TOKEN', '', 'STRING'); - - if (empty($token)) { - throw new InvalidParameterException('Token is required', 403, null, 'token'); - } - - if ($config->get('update_token') !== $token) { - throw new InvalidParameterException('Invalid token', 403, null, 'token'); - } - } } diff --git a/index.php b/index.php index 9609e4e6ccad3..b070eda182c8c 100644 --- a/index.php +++ b/index.php @@ -36,7 +36,10 @@ require_once __DIR__ . '/includes/defines.php'; // Check the existence of an update-extraction config file -if ($_GET['jautoupdate'] === '1' && file_exists(JPATH_ADMINISTRATOR . '/components/com_joomlaupdate/update.php')) { +if ( + !empty($_GET['jautoupdate']) + && is_file(JPATH_ADMINISTRATOR . '/components/com_joomlaupdate/update.php') +) { // Load extraction script and... require_once JPATH_ADMINISTRATOR . '/components/com_joomlaupdate/extract.php'; diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index 322ee28b13498..8193198257810 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -180,7 +180,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'com_redirect', 'component', 'com_redirect', '', 1, 1, 0, 0, 1, '', '', ''), (0, 'com_users', 'component', 'com_users', '', 1, 1, 0, 1, 1, '', '{"allowUserRegistration":"0","new_usertype":"2","guest_usergroup":"9","sendpassword":"0","useractivation":"2","mail_to_admin":"1","captcha":"","frontend_userparams":"1","site_language":"0","change_login_name":"0","reset_count":"10","reset_time":"1","minimum_length":"12","minimum_integers":"0","minimum_symbols":"0","minimum_uppercase":"0","save_history":"1","history_limit":5,"mailSubjectPrefix":"","mailBodySuffix":""}', ''), (0, 'com_finder', 'component', 'com_finder', '', 1, 1, 0, 0, 1, '', '{"enabled":"0","show_description":"1","description_length":255,"allow_empty_query":"0","show_url":"1","show_autosuggest":"1","show_suggested_query":"1","show_explained_query":"1","show_advanced":"1","show_advanced_tips":"1","expand_advanced":"0","show_date_filters":"0","sort_order":"relevance","sort_direction":"desc","highlight_terms":"1","opensearch_name":"","opensearch_description":"","batch_size":"50","title_multiplier":"1.7","text_multiplier":"0.7","meta_multiplier":"1.2","path_multiplier":"2.0","misc_multiplier":"0.3","stem":"1","stemmer":"snowball","enable_logging":"0"}', ''), -(0, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, 1, '', '{"updatesource":"default","customurl":""}', ''), +(0, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, 1, '', '{"updatesource":"default","customurl":"","autoupdate_status":"1","autoupdate":"1"}', ''), (0, 'com_tags', 'component', 'com_tags', '', 1, 1, 1, 0, 1, '', '{"tag_layout":"_:default","save_history":"1","history_limit":5,"show_tag_title":"0","tag_list_show_tag_image":"0","tag_list_show_tag_description":"0","tag_list_image":"","tag_list_orderby":"title","tag_list_orderby_direction":"ASC","show_headings":"0","tag_list_show_date":"0","tag_list_show_item_image":"0","tag_list_show_item_description":"0","tag_list_item_maximum_characters":0,"return_any_or_all":"1","include_children":"0","maximum":200,"tag_list_language_filter":"all","tags_layout":"_:default","all_tags_orderby":"title","all_tags_orderby_direction":"ASC","all_tags_show_tag_image":"0","all_tags_show_tag_description":"0","all_tags_tag_maximum_characters":20,"all_tags_show_tag_hits":"0","filter_field":"1","show_pagination_limit":"1","show_pagination":"2","show_pagination_results":"1","tag_field_ajax_mode":"1","show_feed_link":"1"}', ''), (0, 'com_contenthistory', 'component', 'com_contenthistory', '', 1, 1, 1, 0, 1, '', '', ''), (0, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 1, 1, '', '', ''), diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index 56b2ea8f1918b..6d331c26e0fce 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -186,7 +186,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'com_redirect', 'component', 'com_redirect', '', 1, 1, 0, 0, 1, '', '', '', 0, 0), (0, 'com_users', 'component', 'com_users', '', 1, 1, 0, 1, 1, '', '{"allowUserRegistration":"0","new_usertype":"2","guest_usergroup":"9","sendpassword":"0","useractivation":"2","mail_to_admin":"1","captcha":"","frontend_userparams":"1","site_language":"0","change_login_name":"0","reset_count":"10","reset_time":"1","minimum_length":"12","minimum_integers":"0","minimum_symbols":"0","minimum_uppercase":"0","save_history":"1","history_limit":5,"mailSubjectPrefix":"","mailBodySuffix":""}', '', 0, 0), (0, 'com_finder', 'component', 'com_finder', '', 1, 1, 0, 0, 1, '', '{"enabled":"0","show_description":"1","description_length":255,"allow_empty_query":"0","show_url":"1","show_autosuggest":"1","show_suggested_query":"1","show_explained_query":"1","show_advanced":"1","show_advanced_tips":"1","expand_advanced":"0","show_date_filters":"0","sort_order":"relevance","sort_direction":"desc","highlight_terms":"1","opensearch_name":"","opensearch_description":"","batch_size":"50","title_multiplier":"1.7","text_multiplier":"0.7","meta_multiplier":"1.2","path_multiplier":"2.0","misc_multiplier":"0.3","stem":"1","stemmer":"snowball","enable_logging":"0"}', '', 0, 0), -(0, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, 1, '', '{"updatesource":"default","customurl":""}', '', 0, 0), +(0, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, 1, '', '{"updatesource":"default","customurl":"","autoupdate_status":"1","autoupdate":"1"}', '', 0, 0), (0, 'com_tags', 'component', 'com_tags', '', 1, 1, 1, 0, 1, '', '{"tag_layout":"_:default","save_history":"1","history_limit":5,"show_tag_title":"0","tag_list_show_tag_image":"0","tag_list_show_tag_description":"0","tag_list_image":"","tag_list_orderby":"title","tag_list_orderby_direction":"ASC","show_headings":"0","tag_list_show_date":"0","tag_list_show_item_image":"0","tag_list_show_item_description":"0","tag_list_item_maximum_characters":0,"return_any_or_all":"1","include_children":"0","maximum":200,"tag_list_language_filter":"all","tags_layout":"_:default","all_tags_orderby":"title","all_tags_orderby_direction":"ASC","all_tags_show_tag_image":"0","all_tags_show_tag_description":"0","all_tags_tag_maximum_characters":20,"all_tags_show_tag_hits":"0","filter_field":"1","show_pagination_limit":"1","show_pagination":"2","show_pagination_results":"1","tag_field_ajax_mode":"1","show_feed_link":"1"}', '', 0, 0), (0, 'com_contenthistory', 'component', 'com_contenthistory', '', 1, 1, 1, 0, 1, '', '', '', 0, 0), (0, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 1, 1, '', '', '', 0, 0), diff --git a/libraries/src/Config/ConfigServiceInterface.php b/libraries/src/Config/ConfigServiceInterface.php deleted file mode 100644 index f688f1df79c53..0000000000000 --- a/libraries/src/Config/ConfigServiceInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -namespace Joomla\CMS\Config; - -use Joomla\CMS\Form\Form; - -// phpcs:disable PSR1.Files.SideEffects -\defined('_JEXEC') or die; -// phpcs:enable PSR1.Files.SideEffects - -/** - * Allows manipulating the config form for this component. - * - * @since __DEPLOY_VERSION__ - */ -interface ConfigServiceInterface -{ - /** - * Prepares the config form - * - * @param Form $form The form to change - * @param array|object $data The form data - * - * @return void - */ - public function prepareForm(Form $form, $data): void; -} diff --git a/libraries/src/Config/ConfigServiceTrait.php b/libraries/src/Config/ConfigServiceTrait.php deleted file mode 100644 index 8c9685175324e..0000000000000 --- a/libraries/src/Config/ConfigServiceTrait.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -namespace Joomla\CMS\Config; - -use Joomla\CMS\Form\Form; - -// phpcs:disable PSR1.Files.SideEffects -\defined('_JEXEC') or die; -// phpcs:enable PSR1.Files.SideEffects - -/** - * Trait for component categories service. - * - * @since __DEPLOY_VERSION__ - */ -trait ConfigServiceTrait -{ - /** - * Prepares the config form - * - * @param Form $form The form to change - * @param array|object $data The form data - * - * @return void - */ - public function prepareForm(Form $form, $data): void - { - } -} diff --git a/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php index b760caebe119f..69f74727cda81 100644 --- a/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php @@ -2,7 +2,7 @@ /** * @package Joomla.Plugin - * @subpackage Extension.joomla + * @subpackage Extension.joomlaupdate * * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt @@ -11,8 +11,16 @@ namespace Joomla\Plugin\Extension\Joomlaupdate\Extension; use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\User\BeforeSaveEvent; +use Joomla\CMS\Factory; +use Joomla\CMS\Http\HttpFactory; +use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\CMS\Uri\Uri; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateState; use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; +use Joomla\Event\DispatcherInterface; use Joomla\Event\SubscriberInterface; use Joomla\Registry\Registry; @@ -46,10 +54,53 @@ final class Joomlaupdate extends CMSPlugin implements SubscriberInterface public static function getSubscribedEvents(): array { return [ + 'onExtensionBeforeSave' => 'onExtensionBeforeSave', 'onExtensionAfterSave' => 'onExtensionAfterSave', ]; } + /** + * Handles subscribe or unsubscribe from automated updates + * + * @param BeforeSaveEvent $event + * + * @return void + * @throws \Exception + * + * @since __DEPLOY_VERSION__ + */ + public function onExtensionBeforeSave(\Joomla\CMS\Event\Model\BeforeSaveEvent $event) + { + $context = $event->getArgument('context'); + $table = $event->getArgument('subject'); + + if ($context !== 'com_config.component') { + return; + } + + $data = new Registry($table->params); + + $autoupdateStatus = (int)$data->get('autoupdate'); + $autoupdateRegisterStatus = (int)$data->get('autoupdate_status'); + + if ($data->get('updatesource') !== 'default' || $data->get('minimum_stability') !== '4') { + // If we are not using Joomla Update Server or not using Stable Version disable the autoupdate + if ($autoupdateRegisterStatus !== AutoupdateRegisterState::Unsubscribed->value) { + $data->set('autoupdate_status', AutoupdateRegisterState::Unsubscribe->value); + } + } elseif ($autoupdateStatus === AutoupdateState::Enabled->value) { + // If autoupdate is enabled and we are not subscribed force subscription process + if ($autoupdateRegisterStatus !== AutoupdateRegisterState::Subscribed->value) { + $data->set('autoupdate_status', AutoupdateRegisterState::Subscribe->value); + } + } elseif ($autoupdateRegisterStatus !== AutoupdateRegisterState::Unsubscribed->value) { + // If autoupdate is disabled and we are not unsubscribed force unsubscription process + $data->set('autoupdate_status', AutoupdateRegisterState::Unsubscribe->value); + } + + $table->params = $data->toString(); + } + /** * After update of an extension * @@ -57,18 +108,18 @@ public static function getSubscribedEvents(): array * * @return void * - * @since 5.3.0 + * @since __DEPLOY_VERSION__ */ public function onExtensionAfterSave(AfterSaveEvent $event): void { - $context = $event->getContext(); - $item = $event->getItem(); + $context = $event->getArgument('context'); + $table = $event->getArgument('subject'); if ($context !== 'com_config.component') { return; } - if ($item->element !== 'com_joomlaupdate') { + if ($table->element !== 'com_joomlaupdate') { return; } @@ -80,12 +131,40 @@ public function onExtensionAfterSave(AfterSaveEvent $event): void return; } - $params = new Registry($item->params); + $data = new Registry($table->params); // Apply updated config $updateModel->applyUpdateSite( - $params->get('updatesource'), - $params->get('customurl'), + $data->get('updatesource'), + $data->get('customurl'), + ); + + // Handle autoupdate register changes + $autoupdateRegisterStatus = AutoupdateRegisterState::from((int)$data->get('autoupdate_status')); + + // Check if action is required + if ($autoupdateRegisterStatus === AutoupdateRegisterState::Unsubscribed + || $autoupdateRegisterStatus === AutoupdateRegisterState::Subscribed + ) { + return; + } + + $registerStatus = $updateModel->changeAutoUpdateRegistration($autoupdateRegisterStatus); + + if (!$registerStatus) { + return; + } + + // Load the messages + $this->getApplication()->getLanguage()->load('com_joomlaupdate'); + + Factory::getApplication()->enqueueMessage( + Text::_( + $autoupdateRegisterStatus === AutoupdateRegisterState::Subscribe + ? 'COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS' + : 'COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS' + ), + 'info' ); } } From afff807507fd4201088fe2ee6f8e191d16cdfee7 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 12:51:22 +0100 Subject: [PATCH 051/130] fix result --- .../com_joomlaupdate/src/Controller/UpdateController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index f7d707b8978c4..c2a9766f7bd26 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -739,11 +739,11 @@ public function healthstatus() if ($registrationState === AutoupdateRegisterState::Subscribe) { /** @var UpdateModel $model */ $model = $this->getModel('Update'); - $model->changeAutoUpdateRegistration($registrationState); + $result = $model->changeAutoUpdateRegistration($registrationState); $result = [ 'active' => true, - 'healthy' => true + 'healthy' => $result ]; echo json_encode($result); From 7fd056b0eb2e78c96b19421a35a7d7c4322349f1 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 12:53:26 +0100 Subject: [PATCH 052/130] Added acl check for autoupdate registration --- .../com_joomlaupdate/src/Controller/UpdateController.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index c2a9766f7bd26..39f653bd5d98b 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -736,7 +736,9 @@ public function healthstatus() // Edge case: the current state requires the registration, i.e. because it's a new installation $registrationState = AutoupdateRegisterState::tryFrom($params->get('autoupdate_status', '')); - if ($registrationState === AutoupdateRegisterState::Subscribe) { + if ($this->app->getIdentity()->authorise('core.admin') + && $registrationState === AutoupdateRegisterState::Subscribe + ) { /** @var UpdateModel $model */ $model = $this->getModel('Update'); $result = $model->changeAutoUpdateRegistration($registrationState); From f1e6ae29ac26ac0b04d59ed955b4a1f5fdb35e0a Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 12:54:41 +0100 Subject: [PATCH 053/130] fix cast --- .../components/com_joomlaupdate/src/Model/UpdateModel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index 4598d6223c2d5..b1fff24415c75 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -592,8 +592,8 @@ public function changeAutoUpdateRegistration(AutoupdateRegisterState $targetStat $params->set( 'autoupdate_status', ($targetState === AutoupdateRegisterState::Subscribe) - ? AutoupdateRegisterState::Subscribed - : AutoupdateRegisterState::Unsubscribed + ? AutoupdateRegisterState::Subscribed->value + : AutoupdateRegisterState::Unsubscribed->value ); $extension->params = $params->toString(); From 6372390cc492fddce1e4d33fc8f52445138a857f Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 12:54:50 +0100 Subject: [PATCH 054/130] Fix acl check --- .../com_joomlaupdate/src/Controller/UpdateController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 39f653bd5d98b..41199acabc898 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -736,7 +736,7 @@ public function healthstatus() // Edge case: the current state requires the registration, i.e. because it's a new installation $registrationState = AutoupdateRegisterState::tryFrom($params->get('autoupdate_status', '')); - if ($this->app->getIdentity()->authorise('core.admin') + if ($this->app->getIdentity()->authorise('core.admin', 'com_joomlaupdate') && $registrationState === AutoupdateRegisterState::Subscribe ) { /** @var UpdateModel $model */ From 6fca69164983a69c3b14c91a0ccc4c02f2925453 Mon Sep 17 00:00:00 2001 From: hleithner Date: Sat, 15 Mar 2025 13:00:19 +0100 Subject: [PATCH 055/130] Add Postinstallation Message --- .../sql/updates/mysql/5.3.0-2025-03-15.sql | 3 + .../updates/postgresql/5.3.0-2025-03-15.sql | 3 + .../postinstall/autoupdate.php | 62 +++++++++++++++++++ .../language/en-GB/com_joomlaupdate.ini | 3 + installation/sql/mysql/supports.sql | 2 + installation/sql/postgresql/supports.sql | 2 + 6 files changed, 75 insertions(+) create mode 100644 administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-15.sql create mode 100644 administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-15.sql create mode 100644 administrator/components/com_joomlaupdate/postinstall/autoupdate.php diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-15.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-15.sql new file mode 100644 index 0000000000000..b202f3249483c --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-15.sql @@ -0,0 +1,3 @@ +-- add post-installation messaged for automated updates +INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) +SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.3.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-15.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-15.sql new file mode 100644 index 0000000000000..8f4e9b2a50afc --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-15.sql @@ -0,0 +1,3 @@ +-- add post-installation messaged for automated updates +INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") +SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.3.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; diff --git a/administrator/components/com_joomlaupdate/postinstall/autoupdate.php b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php new file mode 100644 index 0000000000000..59249a4b3dc3d --- /dev/null +++ b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php @@ -0,0 +1,62 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateState; +use Joomla\Database\DatabaseInterface; +use Joomla\Database\ParameterType; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Post-installation message about the new Multi-factor Authentication: condition check. + * + * Returns true if neither of the two new core MFA plugins are enabled. + * + * @return AutoupdateState + * @since __DEPLOY_VERSION__ + */ +function com_joomlaupdate_postinstall_autoupdate_condition(): AutoupdateState +{ + return AutoupdateState::tryFrom(ComponentHelper::getParams('com_joomlaupdate')->get('autoupdate', '0')) === AutoupdateState::Disabled; +} + +/** + * Post-installation message about the new Multi-factor Authentication: action. + * + * Enables the core MFA plugins. + * + * @return void + * @since 4.2.0 + */ +function com_joomlaupdate_postinstall_autoupdate_action(): void +{ + $db = Factory::getContainer()->get(DatabaseInterface::class); + // Get extension row + $extension = new Extension($db); + $extensionId = $extension->find(['element' => 'com_joomlaupdate']); + $extension->load($extensionId); + + // Set new update registration state + $params = new Registry($extension->params); + $params->set('autoupdate', AutoupdateState::Enabled); + $params->set('autoupdate_status', AutoupdateRegisterState::Subscribe); + + $extension->params = $params->toString(); + + if (!$extension->store()) { + throw new \RuntimeException($extension->getError()); + } +} diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 3f2da9f4c9dc4..ad8bea39bbc3a 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -63,6 +63,9 @@ COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_REASON_DATABASE="Your %1$s version \"%2$s COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_REASON_PHP="Your PHP version \"%1$s\" is lower than \"%2$s\"." COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_TITLE="This site can't be updated to Joomla %1$s" COM_JOOMLAUPDATE_OVERVIEW="Joomla Update" +COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION="Active Automated Updates" +COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION="Joomla 5.3 now supports Automated updates for better security and performance. Click \"Activate Automated Updates\" to stay up to date effortlessly!" +COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE="Automated Joomla Updates" COM_JOOMLAUPDATE_PREUPDATE_CHECK_CAPTION="Server settings to check before update." COM_JOOMLAUPDATE_PREUPDATE_CHECK_COMPLETED_YOU_HAVE_DANGEROUS_PLUGINS="There are plugins installed and enabled that could interfere with the Joomla update and result in a failed update that leaves the site inaccessible.

You are strongly advised to update, disable or uninstall these plugins before upgrading." COM_JOOMLAUPDATE_PREUPDATE_CHECK_EXTENSION_AUTHOR_URL="Extension Author URL" diff --git a/installation/sql/mysql/supports.sql b/installation/sql/mysql/supports.sql index bf0a661b0ba37..5b9dd8a8c246d 100644 --- a/installation/sql/mysql/supports.sql +++ b/installation/sql/mysql/supports.sql @@ -278,6 +278,8 @@ INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description SELECT `extension_id`, 'PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_TITLE', 'PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_BODY', 'PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_ACTION', 'plg_system_httpheaders', 1, 'action', 'site://plugins/system/httpheaders/postinstall/introduction.php', 'httpheaders_postinstall_action', 'site://plugins/system/httpheaders/postinstall/introduction.php', 'httpheaders_postinstall_condition', '4.0.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) SELECT `extension_id`, 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_TITLE', 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_BODY', 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_ACTION', 'com_users', 1, 'action', 'admin://components/com_users/postinstall/multifactorauth.php', 'com_users_postinstall_mfa_action', 'admin://components/com_users/postinstall/multifactorauth.php', 'com_users_postinstall_mfa_condition', '4.2.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; +INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) +SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.3.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; -- -------------------------------------------------------- diff --git a/installation/sql/postgresql/supports.sql b/installation/sql/postgresql/supports.sql index 1478ef3ce2575..387add47f692e 100644 --- a/installation/sql/postgresql/supports.sql +++ b/installation/sql/postgresql/supports.sql @@ -289,6 +289,8 @@ INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description SELECT "extension_id", 'PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_TITLE', 'PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_BODY', 'PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_ACTION', 'plg_system_httpheaders', 1, 'action', 'site://plugins/system/httpheaders/postinstall/introduction.php', 'httpheaders_postinstall_action', 'site://plugins/system/httpheaders/postinstall/introduction.php', 'httpheaders_postinstall_condition', '4.0.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") SELECT "extension_id", 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_TITLE', 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_BODY', 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_ACTION', 'com_users', 1, 'action', 'admin://components/com_users/postinstall/multifactorauth.php', 'com_users_postinstall_mfa_action', 'admin://components/com_users/postinstall/multifactorauth.php', 'com_users_postinstall_mfa_condition', '4.2.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; +INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") +SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.3.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; -- -- Table structure for table `#__ucm_base` From 1ca566841c9c24e713cb15aa76394ba2a5353568 Mon Sep 17 00:00:00 2001 From: hleithner Date: Sat, 15 Mar 2025 13:24:01 +0100 Subject: [PATCH 056/130] Update Postinstallation action --- .../postinstall/autoupdate.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/administrator/components/com_joomlaupdate/postinstall/autoupdate.php b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php index 59249a4b3dc3d..5ace28f23044f 100644 --- a/administrator/components/com_joomlaupdate/postinstall/autoupdate.php +++ b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php @@ -10,42 +10,42 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; -use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Table\Extension; use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateState; use Joomla\Database\DatabaseInterface; -use Joomla\Database\ParameterType; +use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** - * Post-installation message about the new Multi-factor Authentication: condition check. + * Post-installation message about the new Automated Update: condition check. * - * Returns true if neither of the two new core MFA plugins are enabled. + * Returns true it is disabled. * - * @return AutoupdateState + * @return bool * @since __DEPLOY_VERSION__ */ -function com_joomlaupdate_postinstall_autoupdate_condition(): AutoupdateState +function com_joomlaupdate_postinstall_autoupdate_condition(): bool { return AutoupdateState::tryFrom(ComponentHelper::getParams('com_joomlaupdate')->get('autoupdate', '0')) === AutoupdateState::Disabled; } /** - * Post-installation message about the new Multi-factor Authentication: action. + * Post-installation message about the new Automated Update: action. * - * Enables the core MFA plugins. + * Enables the Automated Update. * * @return void - * @since 4.2.0 + * @since __DEPLOY_VERSION__ */ function com_joomlaupdate_postinstall_autoupdate_action(): void { $db = Factory::getContainer()->get(DatabaseInterface::class); // Get extension row - $extension = new Extension($db); + $extension = new Extension($db); $extensionId = $extension->find(['element' => 'com_joomlaupdate']); $extension->load($extensionId); From 3e6ef4e5627d8137454ee21b706d9b3491ecb8f8 Mon Sep 17 00:00:00 2001 From: Brian Teeman Date: Sat, 15 Mar 2025 12:39:00 +0000 Subject: [PATCH 057/130] fix copyright an subpackage simple copy paste error --- .../components/com_joomlaupdate/postinstall/autoupdate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_joomlaupdate/postinstall/autoupdate.php b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php index 5ace28f23044f..9324309d9a8a9 100644 --- a/administrator/components/com_joomlaupdate/postinstall/autoupdate.php +++ b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php @@ -2,9 +2,9 @@ /** * @package Joomla.Administrator - * @subpackage com_users + * @subpackage com_joomlaupdate * - * @copyright (C) 2022 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ From a6cbb3f199835e2d5b9198eb2a74ef3999f482f3 Mon Sep 17 00:00:00 2001 From: Brian Teeman Date: Sat, 15 Mar 2025 12:44:14 +0000 Subject: [PATCH 058/130] Update com_joomlaupdate.ini Throughout Joomla we avoid the word "click" as you can only click with a mouse and not with a screen reader or phone. Usually we use the word "select" --- administrator/language/en-GB/com_joomlaupdate.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index ad8bea39bbc3a..f588a7ab6283a 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -64,7 +64,7 @@ COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_REASON_PHP="Your PHP version \"%1$s\" is COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_TITLE="This site can't be updated to Joomla %1$s" COM_JOOMLAUPDATE_OVERVIEW="Joomla Update" COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION="Active Automated Updates" -COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION="Joomla 5.3 now supports Automated updates for better security and performance. Click \"Activate Automated Updates\" to stay up to date effortlessly!" +COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION="Joomla 5.3 now supports Automated updates for better security and performance. Select \"Activate Automated Updates\" to stay up to date effortlessly!" COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE="Automated Joomla Updates" COM_JOOMLAUPDATE_PREUPDATE_CHECK_CAPTION="Server settings to check before update." COM_JOOMLAUPDATE_PREUPDATE_CHECK_COMPLETED_YOU_HAVE_DANGEROUS_PLUGINS="There are plugins installed and enabled that could interfere with the Joomla update and result in a failed update that leaves the site inaccessible.

You are strongly advised to update, disable or uninstall these plugins before upgrading." From caa07f3f52079f13f56b59b729c991d99be51996 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 16:37:01 +0100 Subject: [PATCH 059/130] remove unused variable --- .../com_joomlaupdate/src/Controller/UpdatesController.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php index 83c88279b9014..abd11aacede8e 100644 --- a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -127,8 +127,6 @@ protected function prepareView() throw new \RuntimeException($e->getMessage()); } - $modelName = $this->input->get('model', $this->contentType); - /** @var UpdateModel $model */ $model = $this->getModel('Update', 'Administrator', ['ignore_request' => true, 'state' => $this->modelState]); From 578d43e261094339d8fa7a0b5896d88b202c0c0b Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 16:51:23 +0100 Subject: [PATCH 060/130] fix default value for minimum_stability --- installation/sql/mysql/base.sql | 2 +- installation/sql/postgresql/base.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index 8193198257810..fdc305d4c2307 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -180,7 +180,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'com_redirect', 'component', 'com_redirect', '', 1, 1, 0, 0, 1, '', '', ''), (0, 'com_users', 'component', 'com_users', '', 1, 1, 0, 1, 1, '', '{"allowUserRegistration":"0","new_usertype":"2","guest_usergroup":"9","sendpassword":"0","useractivation":"2","mail_to_admin":"1","captcha":"","frontend_userparams":"1","site_language":"0","change_login_name":"0","reset_count":"10","reset_time":"1","minimum_length":"12","minimum_integers":"0","minimum_symbols":"0","minimum_uppercase":"0","save_history":"1","history_limit":5,"mailSubjectPrefix":"","mailBodySuffix":""}', ''), (0, 'com_finder', 'component', 'com_finder', '', 1, 1, 0, 0, 1, '', '{"enabled":"0","show_description":"1","description_length":255,"allow_empty_query":"0","show_url":"1","show_autosuggest":"1","show_suggested_query":"1","show_explained_query":"1","show_advanced":"1","show_advanced_tips":"1","expand_advanced":"0","show_date_filters":"0","sort_order":"relevance","sort_direction":"desc","highlight_terms":"1","opensearch_name":"","opensearch_description":"","batch_size":"50","title_multiplier":"1.7","text_multiplier":"0.7","meta_multiplier":"1.2","path_multiplier":"2.0","misc_multiplier":"0.3","stem":"1","stemmer":"snowball","enable_logging":"0"}', ''), -(0, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, 1, '', '{"updatesource":"default","customurl":"","autoupdate_status":"1","autoupdate":"1"}', ''), +(0, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, 1, '', '{"updatesource":"default","customurl":"","autoupdate_status":"1","autoupdate":"1","minimum_stability":"4"}', ''), (0, 'com_tags', 'component', 'com_tags', '', 1, 1, 1, 0, 1, '', '{"tag_layout":"_:default","save_history":"1","history_limit":5,"show_tag_title":"0","tag_list_show_tag_image":"0","tag_list_show_tag_description":"0","tag_list_image":"","tag_list_orderby":"title","tag_list_orderby_direction":"ASC","show_headings":"0","tag_list_show_date":"0","tag_list_show_item_image":"0","tag_list_show_item_description":"0","tag_list_item_maximum_characters":0,"return_any_or_all":"1","include_children":"0","maximum":200,"tag_list_language_filter":"all","tags_layout":"_:default","all_tags_orderby":"title","all_tags_orderby_direction":"ASC","all_tags_show_tag_image":"0","all_tags_show_tag_description":"0","all_tags_tag_maximum_characters":20,"all_tags_show_tag_hits":"0","filter_field":"1","show_pagination_limit":"1","show_pagination":"2","show_pagination_results":"1","tag_field_ajax_mode":"1","show_feed_link":"1"}', ''), (0, 'com_contenthistory', 'component', 'com_contenthistory', '', 1, 1, 1, 0, 1, '', '', ''), (0, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 1, 1, '', '', ''), diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index 6d331c26e0fce..0ec28474258de 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -186,7 +186,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'com_redirect', 'component', 'com_redirect', '', 1, 1, 0, 0, 1, '', '', '', 0, 0), (0, 'com_users', 'component', 'com_users', '', 1, 1, 0, 1, 1, '', '{"allowUserRegistration":"0","new_usertype":"2","guest_usergroup":"9","sendpassword":"0","useractivation":"2","mail_to_admin":"1","captcha":"","frontend_userparams":"1","site_language":"0","change_login_name":"0","reset_count":"10","reset_time":"1","minimum_length":"12","minimum_integers":"0","minimum_symbols":"0","minimum_uppercase":"0","save_history":"1","history_limit":5,"mailSubjectPrefix":"","mailBodySuffix":""}', '', 0, 0), (0, 'com_finder', 'component', 'com_finder', '', 1, 1, 0, 0, 1, '', '{"enabled":"0","show_description":"1","description_length":255,"allow_empty_query":"0","show_url":"1","show_autosuggest":"1","show_suggested_query":"1","show_explained_query":"1","show_advanced":"1","show_advanced_tips":"1","expand_advanced":"0","show_date_filters":"0","sort_order":"relevance","sort_direction":"desc","highlight_terms":"1","opensearch_name":"","opensearch_description":"","batch_size":"50","title_multiplier":"1.7","text_multiplier":"0.7","meta_multiplier":"1.2","path_multiplier":"2.0","misc_multiplier":"0.3","stem":"1","stemmer":"snowball","enable_logging":"0"}', '', 0, 0), -(0, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, 1, '', '{"updatesource":"default","customurl":"","autoupdate_status":"1","autoupdate":"1"}', '', 0, 0), +(0, 'com_joomlaupdate', 'component', 'com_joomlaupdate', '', 1, 1, 0, 1, 1, '', '{"updatesource":"default","customurl":"","autoupdate_status":"1","autoupdate":"1","minimum_stability":"4"}', '', 0, 0), (0, 'com_tags', 'component', 'com_tags', '', 1, 1, 1, 0, 1, '', '{"tag_layout":"_:default","save_history":"1","history_limit":5,"show_tag_title":"0","tag_list_show_tag_image":"0","tag_list_show_tag_description":"0","tag_list_image":"","tag_list_orderby":"title","tag_list_orderby_direction":"ASC","show_headings":"0","tag_list_show_date":"0","tag_list_show_item_image":"0","tag_list_show_item_description":"0","tag_list_item_maximum_characters":0,"return_any_or_all":"1","include_children":"0","maximum":200,"tag_list_language_filter":"all","tags_layout":"_:default","all_tags_orderby":"title","all_tags_orderby_direction":"ASC","all_tags_show_tag_image":"0","all_tags_show_tag_description":"0","all_tags_tag_maximum_characters":20,"all_tags_show_tag_hits":"0","filter_field":"1","show_pagination_limit":"1","show_pagination":"2","show_pagination_results":"1","tag_field_ajax_mode":"1","show_feed_link":"1"}', '', 0, 0), (0, 'com_contenthistory', 'component', 'com_contenthistory', '', 1, 1, 1, 0, 1, '', '', '', 0, 0), (0, 'com_ajax', 'component', 'com_ajax', '', 1, 1, 1, 1, 1, '', '', '', 0, 0), From 69eac5a8910d3c0b259f4eb32343453793c224d8 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 16:51:25 +0100 Subject: [PATCH 061/130] cs fix --- .../com_joomlaupdate/src/Controller/HealthcheckController.php | 2 -- .../com_joomlaupdate/src/Controller/UpdatesController.php | 1 - 2 files changed, 3 deletions(-) diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index cb7eecdc77b35..dd6323aeef69a 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -67,8 +67,6 @@ public function show() throw new \RuntimeException($e->getMessage()); } - $modelName = $this->input->get('model', $this->contentType); - /** @var UpdateModel $model */ $model = $this->getModel('Update', 'Administrator', ['ignore_request' => true, 'state' => $this->modelState]); diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php index abd11aacede8e..93878b8967efc 100644 --- a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -110,7 +110,6 @@ public function finalizeUpdate() */ protected function prepareView() { - $viewType = $this->app->getDocument()->getType(); $viewName = $this->input->get('view', $this->default_view); $viewLayout = $this->input->get('layout', 'default', 'string'); From d3ab596b740cc5b803515257e99201a0dcf6359c Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 15 Mar 2025 16:51:39 +0100 Subject: [PATCH 062/130] Prevent update notification emails when auto updater is active --- .../src/Extension/UpdateNotification.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/plugins/task/updatenotification/src/Extension/UpdateNotification.php b/plugins/task/updatenotification/src/Extension/UpdateNotification.php index c685edb9413ac..44b7f1899504d 100644 --- a/plugins/task/updatenotification/src/Extension/UpdateNotification.php +++ b/plugins/task/updatenotification/src/Extension/UpdateNotification.php @@ -11,6 +11,7 @@ namespace Joomla\Plugin\Task\UpdateNotification\Extension; use Joomla\CMS\Access\Access; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Extension\ExtensionHelper; use Joomla\CMS\Mail\Exception\MailDisabledException; use Joomla\CMS\Mail\MailTemplate; @@ -19,6 +20,7 @@ use Joomla\CMS\Updater\Updater; use Joomla\CMS\Uri\Uri; use Joomla\CMS\Version; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; use Joomla\Component\Scheduler\Administrator\Event\ExecuteTaskEvent; use Joomla\Component\Scheduler\Administrator\Task\Status; use Joomla\Component\Scheduler\Administrator\Traits\TaskPluginTrait; @@ -92,6 +94,16 @@ private function sendNotification(ExecuteTaskEvent $event): int $specificEmail = $event->getArgument('params')->email ?? ''; $forcedLanguage = $event->getArgument('params')->language_override ?? ''; + $updateParams = ComponentHelper::getParams('com_joomlaupdate'); + + // Don't send when automated updates are active and working + $registrationState = AutoupdateRegisterState::tryFrom($updateParams->get('autoupdate_status', '')); + $lastUpdateCheck = date_create_from_format('Y-m-d H:i:s', $updateParams->get('update_last_check', '')); + + if ($registrationState === AutoupdateRegisterState::Subscribed && $lastUpdateCheck !== false && $lastUpdateCheck->diff(new \DateTime())->days < 4) { + return Status::OK; + } + // This is the extension ID for Joomla! itself $eid = ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id; From b9e35971f87f53bf719b24a79a6e8b10fd980621 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 17:01:41 +0100 Subject: [PATCH 063/130] Call cleanup method and trigger actionlog --- .../src/View/Updates/JsonapiView.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index cf81d01b3f724..dae4ecb30d271 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -11,7 +11,9 @@ namespace Joomla\Component\Joomlaupdate\Api\View\Updates; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; +use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Uri\Uri; use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; use Tobscure\JsonApi\Resource; @@ -95,11 +97,23 @@ public function finalizeUpdate() $model = $this->getModel(); try { + // Perform the finalization action $model->finaliseUpgrade(); } catch (\Throwable $e) { $model->collectError('finaliseUpgrade', $e); } + try { + // Load actionlog plugins. + PluginHelper::importPlugin('actionlog'); + + // Perform the cleanup action + $model->cleanUp(); + } catch (\Throwable $e) { + $model->collectError('cleanUp', $e); + } + + // Reset source $model->resetUpdateSource(); $success = true; From 809ce637ff871ce720c2549f0cae7b55ce4bbcd5 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 19:43:16 +0100 Subject: [PATCH 064/130] Adjust actionlog item for automated updates --- administrator/language/en-GB/plg_actionlog_joomla.ini | 1 + .../com_joomlaupdate/src/Controller/UpdatesController.php | 4 +++- .../com_joomlaupdate/src/View/Updates/JsonapiView.php | 5 ++++- plugins/actionlog/joomla/src/Extension/Joomla.php | 5 ++++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/administrator/language/en-GB/plg_actionlog_joomla.ini b/administrator/language/en-GB/plg_actionlog_joomla.ini index 69d026dbc27e8..c1f36df418911 100644 --- a/administrator/language/en-GB/plg_actionlog_joomla.ini +++ b/administrator/language/en-GB/plg_actionlog_joomla.ini @@ -55,6 +55,7 @@ PLG_ACTIONLOG_JOOMLA_USER_RESET_COMPLETE="User {username PLG_ACTIONLOG_JOOMLA_USER_RESET_REQUEST="User {username} requested a password reset for their account" PLG_ACTIONLOG_JOOMLA_USER_UNBLOCK="User {username} unblocked user {title}" PLG_ACTIONLOG_JOOMLA_USER_UPDATE="User {username} updated Joomla from {oldversion} to {version}" +PLG_ACTIONLOG_JOOMLA_SYSTEM_UPDATE="A automated process updated Joomla from {oldversion} to {version}" ; Component PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED="User {username} changed settings of the application configuration" PLG_ACTIONLOG_JOOMLA_COMPONENT_CONFIG_UPDATED="User {username} changed settings of the component {extension_name}" diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php index 93878b8967efc..2d0a287662b2c 100644 --- a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -96,9 +96,11 @@ public function finalizeUpdate() { $this->validateUpdateToken(); + $fromVersion = $this->input->json->getString('fromVersion', null); + $view = $this->prepareView(); - $view->finalizeUpdate(); + $view->finalizeUpdate($fromVersion); return $this; } diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index dae4ecb30d271..0b7c5ac3ce71b 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -89,13 +89,16 @@ public function prepareUpdate(string $targetVersion): string return $this->getDocument()->render(); } - public function finalizeUpdate() + public function finalizeUpdate($fromVersion) { /** * @var UpdateModel $model */ $model = $this->getModel(); + // Write old version to state for usage in model + Factory::getApplication()->setUserState('com_joomlaupdate.oldversion', $fromVersion); + try { // Perform the finalization action $model->finaliseUpgrade(); diff --git a/plugins/actionlog/joomla/src/Extension/Joomla.php b/plugins/actionlog/joomla/src/Extension/Joomla.php index 97cda770a924d..9069342fcfc70 100644 --- a/plugins/actionlog/joomla/src/Extension/Joomla.php +++ b/plugins/actionlog/joomla/src/Extension/Joomla.php @@ -1186,7 +1186,10 @@ public function onJoomlaAfterUpdate(Event $event): void 'version' => JVERSION, 'oldversion' => $oldVersion, ]; - $this->addLog([$message], 'PLG_ACTIONLOG_JOOMLA_USER_UPDATE', $context, $user->id); + + $messageKey = ($user->id) ? 'PLG_ACTIONLOG_JOOMLA_USER_UPDATE' : 'PLG_ACTIONLOG_JOOMLA_SYSTEM_UPDATE'; + + $this->addLog([$message], $messageKey, $context, $user->id); } /** From 2623378f28e5c1ee2ea92ba83ea982737371d195 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 19:44:06 +0100 Subject: [PATCH 065/130] added tempaltes to initial dataset --- installation/sql/mysql/supports.sql | 2 ++ installation/sql/postgresql/supports.sql | 2 ++ 2 files changed, 4 insertions(+) diff --git a/installation/sql/mysql/supports.sql b/installation/sql/mysql/supports.sql index 5b9dd8a8c246d..ee2762809f088 100644 --- a/installation/sql/mysql/supports.sql +++ b/installation/sql/mysql/supports.sql @@ -416,6 +416,8 @@ INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subjec ('com_users.massmail.mail', 'com_users', '', 'COM_USERS_MASSMAIL_MAIL_SUBJECT', 'COM_USERS_MASSMAIL_MAIL_BODY', '', '', '{"tags":["subject","body","subjectprefix","bodysuffix"]}'), ('com_users.password_reset', 'com_users', '', 'COM_USERS_EMAIL_PASSWORD_RESET_SUBJECT', 'COM_USERS_EMAIL_PASSWORD_RESET_BODY', '', '', '{"tags":["name","email","sitename","link_text","link_html","token"]}'), ('com_users.reminder', 'com_users','', 'COM_USERS_EMAIL_USERNAME_REMINDER_SUBJECT', 'COM_USERS_EMAIL_USERNAME_REMINDER_BODY', '', '', '{"tags":["name","username","sitename","email","link_text","link_html"]}'), +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), ('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'), ('plg_user_joomla.mail', 'plg_user_joomla', '', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_SUBJECT', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_BODY', '', '', '{"tags":["name","sitename","url","username","password","email"]}'), ('com_actionlogs.notification', 'com_actionlogs', '', 'COM_ACTIONLOGS_EMAIL_SUBJECT', 'COM_ACTIONLOGS_EMAIL_BODY', 'COM_ACTIONLOGS_EMAIL_HTMLBODY', '', '{"tags":["messages","message","date","extension","username"]}'), diff --git a/installation/sql/postgresql/supports.sql b/installation/sql/postgresql/supports.sql index 387add47f692e..1eb4ea5ddfe43 100644 --- a/installation/sql/postgresql/supports.sql +++ b/installation/sql/postgresql/supports.sql @@ -427,6 +427,8 @@ INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subjec ('com_users.massmail.mail', 'com_users', '', 'COM_USERS_MASSMAIL_MAIL_SUBJECT', 'COM_USERS_MASSMAIL_MAIL_BODY', '', '', '{"tags":["subject","body","subjectprefix","bodysuffix"]}'), ('com_users.password_reset', 'com_users', '', 'COM_USERS_EMAIL_PASSWORD_RESET_SUBJECT', 'COM_USERS_EMAIL_PASSWORD_RESET_BODY', '', '', '{"tags":["name","email","sitename","link_text","link_html","token"]}'), ('com_users.reminder', 'com_users', '', 'COM_USERS_EMAIL_USERNAME_REMINDER_SUBJECT', 'COM_USERS_EMAIL_USERNAME_REMINDER_BODY', '', '', '{"tags":["name","username","sitename","email","link_text","link_html"]}'), +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), ('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'), ('plg_user_joomla.mail', 'plg_user_joomla', '', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_SUBJECT', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_BODY', '', '', '{"tags":["name","sitename","url","username","password","email"]}'), ('com_actionlogs.notification', 'com_actionlogs', '', 'COM_ACTIONLOGS_EMAIL_SUBJECT', 'COM_ACTIONLOGS_EMAIL_BODY', 'COM_ACTIONLOGS_EMAIL_HTMLBODY', '', '{"tags":["messages","message","date","extension","username"]}'), From d1ce9e1effd35ab5a952e8b02b328f3b4ac85f70 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 19:50:47 +0100 Subject: [PATCH 066/130] added update sqls --- .../com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql | 4 ++++ .../com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql index 5dd0589e35e85..827b801690583 100644 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql +++ b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql @@ -5,3 +5,7 @@ WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'joomlaupdate' AND e.`folder` = 'webservices' AND e.`client_id` = 0); + +INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subject`, `body`, `htmlbody`, `attachments`, `params`) VALUES +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql index 393ba9b51abff..1401f67b2e8b0 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql @@ -5,3 +5,7 @@ WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'joomlaupdate' AND e."folder" = 'webservices' AND e."client_id" = 0); + +INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subject", "body", "htmlbody", "attachments", "params") VALUES +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'); From 07fd78c297ad7231b0b9c6f80a007c403d5ce91d Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 20:19:52 +0100 Subject: [PATCH 067/130] Update administrator/language/en-GB/plg_actionlog_joomla.ini Co-authored-by: Brian Teeman --- administrator/language/en-GB/plg_actionlog_joomla.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/language/en-GB/plg_actionlog_joomla.ini b/administrator/language/en-GB/plg_actionlog_joomla.ini index c1f36df418911..05415c26d6594 100644 --- a/administrator/language/en-GB/plg_actionlog_joomla.ini +++ b/administrator/language/en-GB/plg_actionlog_joomla.ini @@ -55,7 +55,7 @@ PLG_ACTIONLOG_JOOMLA_USER_RESET_COMPLETE="User {username PLG_ACTIONLOG_JOOMLA_USER_RESET_REQUEST="User {username} requested a password reset for their account" PLG_ACTIONLOG_JOOMLA_USER_UNBLOCK="User {username} unblocked user {title}" PLG_ACTIONLOG_JOOMLA_USER_UPDATE="User {username} updated Joomla from {oldversion} to {version}" -PLG_ACTIONLOG_JOOMLA_SYSTEM_UPDATE="A automated process updated Joomla from {oldversion} to {version}" +PLG_ACTIONLOG_JOOMLA_SYSTEM_UPDATE="An automated process updated Joomla from {oldversion} to {version}" ; Component PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED="User {username} changed settings of the application configuration" PLG_ACTIONLOG_JOOMLA_COMPONENT_CONFIG_UPDATED="User {username} changed settings of the component {extension_name}" From a1e339cc3378d523496323c0f5d83ac2f0fc0c2b Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 20:32:23 +0100 Subject: [PATCH 068/130] added mailtemplate texts --- administrator/language/en-GB/com_joomlaupdate.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index f588a7ab6283a..5f9d614377ed4 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -101,6 +101,10 @@ COM_JOOMLAUPDATE_UPDATE_LOG_UNINSTALL_EXTENSIONS="Uninstalling extensions" COM_JOOMLAUPDATE_UPDATE_LOG_UPLOAD="Uploading update file" COM_JOOMLAUPDATE_UPDATE_LOG_URL="Downloading update file from %s." COM_JOOMLAUPDATE_UPDATE_LOGGING_TEST_FAIL="Logging does not work. Make sure the log folder is writable, and try again. The logging test failed with message: %s" +COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site has been successfully automatically updated from {CURVERSION} to {NEWVERSION}.\nPlease check your site for any unexpected behavior or malfunctions.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and the installation of such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" +COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT="Joomla! update failed for {SITENAME} – {URL}" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {CURVERSION} to {NEWVERSION}.\nPlease check the logfile of com_joomlaupdate for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! successfully updated at {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATING_HEAD="Update in progress" COM_JOOMLAUPDATE_UPDATING_INPROGRESS="Please wait; Joomla is being updated. This may take a while." COM_JOOMLAUPDATE_UPDATING_FAIL="The update has failed." From 20701fb06fe67c75963aacd8e782c1ce15596a53 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 21:02:57 +0100 Subject: [PATCH 069/130] remove irrelevant change --- .../com_config/src/Model/ComponentModel.php | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/administrator/components/com_config/src/Model/ComponentModel.php b/administrator/components/com_config/src/Model/ComponentModel.php index 89cdf4cf13796..0a80503e4e836 100644 --- a/administrator/components/com_config/src/Model/ComponentModel.php +++ b/administrator/components/com_config/src/Model/ComponentModel.php @@ -13,7 +13,6 @@ use Joomla\CMS\Access\Access; use Joomla\CMS\Access\Rules; use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Config\ConfigServiceInterface; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; @@ -102,34 +101,6 @@ public function getForm($data = [], $loadData = true) return $form; } - /** - * Method to preprocess the form. - * - * @param Form $form A Form object. - * @param mixed $data The data expected for the form. - * @param string $group The name of the plugin group to import. - * - * @return void - * - * @since __DEPLOY_VERSION__ - * - * @throws \Exception if there is an error in the form event. - * - * @see \Joomla\CMS\Form\FormField - */ - protected function preprocessForm(Form $form, $data, $group = 'content') - { - $component = $this->getState()->get('component.option'); - - $componentInterface = Factory::getApplication()->bootComponent($component); - - if ($componentInterface instanceof ConfigServiceInterface) { - $componentInterface->prepareForm($form, $data); - } - - parent::preprocessForm($form, $data, $group); - } - /** * Method to get the data that should be injected in the form. * From 2ab51cd511d249c7d2f22812b14f3ef557701f56 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 21:15:04 +0100 Subject: [PATCH 070/130] cs fixes --- .../com_joomlaupdate/src/Controller/UpdateController.php | 7 ++++--- .../com_joomlaupdate/src/Enum/AutoupdateRegisterState.php | 8 +++++--- .../com_joomlaupdate/src/Enum/AutoupdateState.php | 2 ++ .../components/com_joomlaupdate/src/Model/UpdateModel.php | 6 +++--- .../com_joomlaupdate/src/View/Updates/JsonapiView.php | 1 - .../extension/joomlaupdate/src/Extension/Joomlaupdate.php | 8 +++----- .../src/Extension/UpdateNotification.php | 2 +- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 41199acabc898..0f1382ca0157a 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -736,16 +736,17 @@ public function healthstatus() // Edge case: the current state requires the registration, i.e. because it's a new installation $registrationState = AutoupdateRegisterState::tryFrom($params->get('autoupdate_status', '')); - if ($this->app->getIdentity()->authorise('core.admin', 'com_joomlaupdate') + if ( + $this->app->getIdentity()->authorise('core.admin', 'com_joomlaupdate') && $registrationState === AutoupdateRegisterState::Subscribe ) { /** @var UpdateModel $model */ - $model = $this->getModel('Update'); + $model = $this->getModel('Update'); $result = $model->changeAutoUpdateRegistration($registrationState); $result = [ 'active' => true, - 'healthy' => $result + 'healthy' => $result, ]; echo json_encode($result); diff --git a/administrator/components/com_joomlaupdate/src/Enum/AutoupdateRegisterState.php b/administrator/components/com_joomlaupdate/src/Enum/AutoupdateRegisterState.php index 4da394b41b645..ba649720383d6 100644 --- a/administrator/components/com_joomlaupdate/src/Enum/AutoupdateRegisterState.php +++ b/administrator/components/com_joomlaupdate/src/Enum/AutoupdateRegisterState.php @@ -10,15 +10,17 @@ namespace Joomla\Component\Joomlaupdate\Administrator\Enum; +// phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects /** * Autoupdate State Enum */ enum AutoupdateRegisterState: int { - case Unsubscribe = -1; + case Unsubscribe = -1; case Unsubscribed = 0; - case Subscribe = 1; - case Subscribed = 2; + case Subscribe = 1; + case Subscribed = 2; } diff --git a/administrator/components/com_joomlaupdate/src/Enum/AutoupdateState.php b/administrator/components/com_joomlaupdate/src/Enum/AutoupdateState.php index cfaedc06dd038..32abd7bbbb5e5 100644 --- a/administrator/components/com_joomlaupdate/src/Enum/AutoupdateState.php +++ b/administrator/components/com_joomlaupdate/src/Enum/AutoupdateState.php @@ -10,7 +10,9 @@ namespace Joomla\Component\Joomlaupdate\Administrator\Enum; +// phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects /** * Autoupdate State Enum diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index b1fff24415c75..869b6499ef85b 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -550,7 +550,7 @@ public function changeAutoUpdateRegistration(AutoupdateRegisterState $targetStat $requestData = [ 'url' => Uri::root(), - 'key' => $this->getAutoUpdateToken() + 'key' => $this->getAutoUpdateToken(), ]; // JHttp transport throws an exception when there's no response. @@ -583,7 +583,7 @@ public function changeAutoUpdateRegistration(AutoupdateRegisterState $targetStat } // Get extension row - $extension = new Extension($this->getDatabase()); + $extension = new Extension($this->getDatabase()); $extensionId = $extension->find(['element' => 'com_joomlaupdate']); $extension->load($extensionId); @@ -615,7 +615,7 @@ public function changeAutoUpdateRegistration(AutoupdateRegisterState $targetStat protected function getAutoUpdateToken(): string { // Get extension row - $extension = new Extension($this->getDatabase()); + $extension = new Extension($this->getDatabase()); $extensionId = $extension->find(['element' => 'com_joomlaupdate']); $extension->load($extensionId); diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index dae4ecb30d271..f54d6d6ca6801 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -11,7 +11,6 @@ namespace Joomla\Component\Joomlaupdate\Api\View\Updates; use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Factory; use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Uri\Uri; diff --git a/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php index 69f74727cda81..6fd22c69f394d 100644 --- a/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php @@ -13,14 +13,11 @@ use Joomla\CMS\Event\Model\AfterSaveEvent; use Joomla\CMS\Event\User\BeforeSaveEvent; use Joomla\CMS\Factory; -use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\CMSPlugin; -use Joomla\CMS\Uri\Uri; use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateState; use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; -use Joomla\Event\DispatcherInterface; use Joomla\Event\SubscriberInterface; use Joomla\Registry\Registry; @@ -55,7 +52,7 @@ public static function getSubscribedEvents(): array { return [ 'onExtensionBeforeSave' => 'onExtensionBeforeSave', - 'onExtensionAfterSave' => 'onExtensionAfterSave', + 'onExtensionAfterSave' => 'onExtensionAfterSave', ]; } @@ -143,7 +140,8 @@ public function onExtensionAfterSave(AfterSaveEvent $event): void $autoupdateRegisterStatus = AutoupdateRegisterState::from((int)$data->get('autoupdate_status')); // Check if action is required - if ($autoupdateRegisterStatus === AutoupdateRegisterState::Unsubscribed + if ( + $autoupdateRegisterStatus === AutoupdateRegisterState::Unsubscribed || $autoupdateRegisterStatus === AutoupdateRegisterState::Subscribed ) { return; diff --git a/plugins/task/updatenotification/src/Extension/UpdateNotification.php b/plugins/task/updatenotification/src/Extension/UpdateNotification.php index 44b7f1899504d..60dee1215617f 100644 --- a/plugins/task/updatenotification/src/Extension/UpdateNotification.php +++ b/plugins/task/updatenotification/src/Extension/UpdateNotification.php @@ -98,7 +98,7 @@ private function sendNotification(ExecuteTaskEvent $event): int // Don't send when automated updates are active and working $registrationState = AutoupdateRegisterState::tryFrom($updateParams->get('autoupdate_status', '')); - $lastUpdateCheck = date_create_from_format('Y-m-d H:i:s', $updateParams->get('update_last_check', '')); + $lastUpdateCheck = date_create_from_format('Y-m-d H:i:s', $updateParams->get('update_last_check', '')); if ($registrationState === AutoupdateRegisterState::Subscribed && $lastUpdateCheck !== false && $lastUpdateCheck->diff(new \DateTime())->days < 4) { return Status::OK; From 7f672880f18884b02a0052116be2f6b70f2b653d Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 21:24:23 +0100 Subject: [PATCH 071/130] re-add defines path --- includes/app.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/includes/app.php b/includes/app.php index 07a24430445ad..349c7446f75cb 100644 --- a/includes/app.php +++ b/includes/app.php @@ -13,6 +13,12 @@ $startTime = microtime(1); $startMem = memory_get_usage(); +if (file_exists(\dirname(__DIR__) . '/defines.php')) { + include_once \dirname(__DIR__) . '/defines.php'; +} + +require_once __DIR__ . '/defines.php'; + // Check for presence of vendor dependencies not included in the git repository if (!file_exists(JPATH_LIBRARIES . '/vendor/autoload.php') || !is_dir(JPATH_PUBLIC . '/media/vendor')) { echo file_get_contents(JPATH_ROOT . '/templates/system/build_incomplete.html'); From 2dba4e87e9439d1bd43c8d7ca3336194b9bf1f00 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 21:30:57 +0100 Subject: [PATCH 072/130] added quickicon to extension helper --- libraries/src/Extension/ExtensionHelper.php | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/src/Extension/ExtensionHelper.php b/libraries/src/Extension/ExtensionHelper.php index 7fea251ed9f5f..42b58ff03cb71 100644 --- a/libraries/src/Extension/ExtensionHelper.php +++ b/libraries/src/Extension/ExtensionHelper.php @@ -266,6 +266,7 @@ class ExtensionHelper ['plugin', 'user', 'privacy', 0], // Core plugin extensions - quick icon + ['plugin', 'autoupdate', 'quickicon', 0], ['plugin', 'downloadkey', 'quickicon', 0], ['plugin', 'extensionupdate', 'quickicon', 0], ['plugin', 'joomlaupdate', 'quickicon', 0], From 4d7fabaac7df3651747b3d7d798370f0325517e6 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 21:31:03 +0100 Subject: [PATCH 073/130] remove unused check --- libraries/src/Updater/ConstraintChecker.php | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/libraries/src/Updater/ConstraintChecker.php b/libraries/src/Updater/ConstraintChecker.php index 26a38445a882e..8b916c94d2151 100644 --- a/libraries/src/Updater/ConstraintChecker.php +++ b/libraries/src/Updater/ConstraintChecker.php @@ -44,13 +44,6 @@ class ConstraintChecker */ protected $channel; - /** - * True if we should stay in the patch release - * - * @var boolean - */ - protected $patchOnly = false; - /** * Constructor, used to populate the failed * @@ -70,11 +63,6 @@ public function __construct($channel = null) $channel = (Version::MAJOR_VERSION + ($params->get('updatesource', 'default') == 'next' ? 1 : 0)) . '.x'; } - // We should stay in the patch release - if ($params->get('patchOnly')) { - $this->patchOnly = true; - } - $this->channel = $channel; } @@ -113,12 +101,6 @@ public function check(array $candidate, $minimumStability = Updater::STABILITY_S return false; } - list($major, $minor) = explode('.', $candidate['version']); - - if ($this->patchOnly && version_compare(Version::MAJOR_VERSION . '.' . Version::MINOR_VERSION, $major . '.' . $minor) !== 0) { - return false; - } - $result = true; // Check php_minimum, assume true when not set From 9e1a412b93b3d03341d875f8fb7cee87ff0787ae Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 21:32:16 +0100 Subject: [PATCH 074/130] cs fix --- libraries/src/Updater/ConstraintChecker.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/src/Updater/ConstraintChecker.php b/libraries/src/Updater/ConstraintChecker.php index 8b916c94d2151..c6952265f2312 100644 --- a/libraries/src/Updater/ConstraintChecker.php +++ b/libraries/src/Updater/ConstraintChecker.php @@ -57,9 +57,9 @@ public function __construct($channel = null) { $this->failedEnvironmentConstraints = new \stdClass(); - $params = ComponentHelper::getParams('com_joomlaupdate'); - if (!isset($channel)) { + $params = ComponentHelper::getParams('com_joomlaupdate'); + $channel = (Version::MAJOR_VERSION + ($params->get('updatesource', 'default') == 'next' ? 1 : 0)) . '.x'; } From 542b97c94961b9e13bcf0fd1e0f426b8d8c208aa Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 15 Mar 2025 22:04:12 +0100 Subject: [PATCH 075/130] fix js codestyles --- .../plg_quickicon_autoupdate/js/healthcheck.es6.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/build/media_source/plg_quickicon_autoupdate/js/healthcheck.es6.js b/build/media_source/plg_quickicon_autoupdate/js/healthcheck.es6.js index 0b2deaf0e6517..273415fffe5eb 100644 --- a/build/media_source/plg_quickicon_autoupdate/js/healthcheck.es6.js +++ b/build/media_source/plg_quickicon_autoupdate/js/healthcheck.es6.js @@ -35,12 +35,10 @@ if (Joomla && Joomla.getOptions('js-auto-update')) { // Not active if (!healthStatus.active) { update('warning', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_DISABLED')); + } else if (!healthStatus.healthy) { + update('danger', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_OUTDATED')); } else { - if (!healthStatus.healthy) { - update('danger', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_OUTDATED')); - } else { - update('success', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_OK')); - } + update('success', Joomla.Text._('PLG_QUICKICON_AUTOUPDATE_OK')); } } else { // An error occurred From 1b1af9d1462eabf99d6bb948b7b56dfc1db999fa Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 15 Mar 2025 22:27:11 +0100 Subject: [PATCH 076/130] Apply suggestions from code review Co-authored-by: Brian Teeman --- administrator/language/en-GB/com_joomlaupdate.ini | 8 ++++---- .../language/en-GB/plg_webservices_joomlaupdate.ini | 2 +- .../language/en-GB/plg_webservices_joomlaupdate.sys.ini | 2 +- plugins/quickicon/autoupdate/autoupdate.xml | 4 ++-- plugins/webservices/joomlaupdate/joomlaupdate.xml | 6 +++--- plugins/webservices/joomlaupdate/services/provider.php | 2 +- .../joomlaupdate/src/Extension/Joomlaupdate.php | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index f588a7ab6283a..8ced7f4e47bcd 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -10,7 +10,7 @@ COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from aut COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." COM_JOOMLAUPDATE_CONFIG_AUTO_UPDATE_DISABLED_LABEL=" Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." -COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_LABEL="Automated updates" +COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_LABEL="Automated Updates" COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_DESC="Automatically update Joomla to the latest version when it is available." COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_LABEL="Automated Update" COM_JOOMLAUPDATE_CONFIG_BACKUPCHECK_DESC="Shows the checkbox to confirm you have taken a backup and you're ready to update in the final step before the update is actually applied." @@ -19,13 +19,13 @@ COM_JOOMLAUPDATE_CONFIG_CUSTOMURL_LABEL="Custom URL" COM_JOOMLAUPDATE_CONFIG_SOURCES_DESC="Configure where Joomla gets its update information from." COM_JOOMLAUPDATE_CONFIG_SOURCES_LABEL="Update Source" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM="Custom URL" -COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_LABEL="Last checked" -COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_DESC="The last time the automated update server could reach this site. If this date is too old, something is wrong with the automated update and you should re-initiate the process by saving the configuration." +COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_LABEL="Last Checked" +COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_DESC="The last time the automated update server could reach this site. If this date is too old, something is wrong with the automated update and you should re-initiate the process by re-saving the configuration." COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM_ERROR="The custom URL field is empty." COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_DEFAULT="Default" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_LABEL="Update Channel" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_NEXT="Joomla Next" -COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_DESC="This is the update token that Joomla uses to authenticate with the Joomla Update Server. It is used to ensure that only your site can update itself." +COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_DESC="This is the update token that this site uses to authenticate with the Joomla Update Server. It is used to ensure that only your site can update itself." COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_LABEL="Update Token" ; Deprecated, will be removed with 6.0 COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_TESTING="Testing" diff --git a/administrator/language/en-GB/plg_webservices_joomlaupdate.ini b/administrator/language/en-GB/plg_webservices_joomlaupdate.ini index 8b4adddcd014b..aace39ac4d9c6 100644 --- a/administrator/language/en-GB/plg_webservices_joomlaupdate.ini +++ b/administrator/language/en-GB/plg_webservices_joomlaupdate.ini @@ -1,5 +1,5 @@ ; Joomla! Project -; (C) 2024 Open Source Matters, Inc. +; (C) 2025 Open Source Matters, Inc. ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 diff --git a/administrator/language/en-GB/plg_webservices_joomlaupdate.sys.ini b/administrator/language/en-GB/plg_webservices_joomlaupdate.sys.ini index 8b4adddcd014b..aace39ac4d9c6 100644 --- a/administrator/language/en-GB/plg_webservices_joomlaupdate.sys.ini +++ b/administrator/language/en-GB/plg_webservices_joomlaupdate.sys.ini @@ -1,5 +1,5 @@ ; Joomla! Project -; (C) 2024 Open Source Matters, Inc. +; (C) 2025 Open Source Matters, Inc. ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 diff --git a/plugins/quickicon/autoupdate/autoupdate.xml b/plugins/quickicon/autoupdate/autoupdate.xml index d858b03624019..8ed7cc372ff25 100644 --- a/plugins/quickicon/autoupdate/autoupdate.xml +++ b/plugins/quickicon/autoupdate/autoupdate.xml @@ -2,12 +2,12 @@ plg_quickicon_autoupdate Joomla! Project - 2025-01 + 2025-03 (C) 2025 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt admin@joomla.org www.joomla.org - 5.0.0 + 5.3.0 PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION Joomla\Plugin\Quickicon\Autoupdate diff --git a/plugins/webservices/joomlaupdate/joomlaupdate.xml b/plugins/webservices/joomlaupdate/joomlaupdate.xml index 0dafe3650471c..f6e11345e491d 100644 --- a/plugins/webservices/joomlaupdate/joomlaupdate.xml +++ b/plugins/webservices/joomlaupdate/joomlaupdate.xml @@ -2,12 +2,12 @@ plg_webservices_joomlaupdate Joomla! Project - 2024-11 - (C) 2024 Open Source Matters, Inc. + 2025-03 + (C) 2025 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt admin@joomla.org www.joomla.org - 5.0.0 + 5.3.0 PLG_WEBSERVICES_JOOMLAUPDATE_XML_DESCRIPTION Joomla\Plugin\WebServices\Joomlaupdate diff --git a/plugins/webservices/joomlaupdate/services/provider.php b/plugins/webservices/joomlaupdate/services/provider.php index 7115b9265b53f..fc785c9670a19 100644 --- a/plugins/webservices/joomlaupdate/services/provider.php +++ b/plugins/webservices/joomlaupdate/services/provider.php @@ -4,7 +4,7 @@ * @package Joomla.Plugin * @subpackage Webservices.Joomlaupdate * - * @copyright (C) 2023 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index 137089abdcefb..dbb1fe3c51b6a 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -4,7 +4,7 @@ * @package Joomla.Plugin * @subpackage Webservices.joomlaupdate * - * @copyright (C) 2020 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ From 991cf2ca2df52ed0281f57ea670b907fa73368af Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 15 Mar 2025 22:28:57 +0100 Subject: [PATCH 077/130] Update administrator/components/com_joomlaupdate/config.xml Co-authored-by: Brian Teeman --- administrator/components/com_joomlaupdate/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index 0ebe422d7906d..ecc5ca046f540 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -85,7 +85,7 @@ layout="joomla.form.field.radio.switcher" showon="updatesource:default[AND]minimum_stability:4" validate="options" - > + >
From f7454b4932b7ddde737da64349d1c2ecd2276558 Mon Sep 17 00:00:00 2001 From: hleithner Date: Sat, 15 Mar 2025 22:32:33 +0100 Subject: [PATCH 078/130] Update notification --- .../sql/updates/mysql/5.3.0-2025-01-18.sql | 4 +- .../updates/postgresql/5.3.0-2025-01-18.sql | 4 +- .../components/com_joomlaupdate/config.xml | 7 + .../src/Model/NotificationModel.php | 176 ++++++++++++++++ .../language/en-GB/com_joomlaupdate.ini | 4 +- .../src/Controller/NotificationController.php | 191 ++++++++++++++++++ .../src/View/Notification/JsonapiView.php | 59 ++++++ installation/sql/mysql/supports.sql | 4 +- installation/sql/postgresql/supports.sql | 4 +- .../src/Extension/Joomlaupdate.php | 2 + 10 files changed, 445 insertions(+), 10 deletions(-) create mode 100644 administrator/components/com_joomlaupdate/src/Model/NotificationModel.php create mode 100644 api/components/com_joomlaupdate/src/Controller/NotificationController.php create mode 100644 api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql index 827b801690583..fb17b040a603e 100644 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql +++ b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql @@ -7,5 +7,5 @@ SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'joomlaupdate' AND e.`folder` = 'webservices' AND e.`client_id` = 0); INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subject`, `body`, `htmlbody`, `attachments`, `params`) VALUES -('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), -('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'); +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql index 1401f67b2e8b0..45371501a8e58 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql @@ -7,5 +7,5 @@ SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'joomlaupdate' AND e."folder" = 'webservices' AND e."client_id" = 0); INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subject", "body", "htmlbody", "attachments", "params") VALUES -('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), -('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'); +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'); diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index 0ebe422d7906d..946d4356d1df4 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -118,5 +118,12 @@ class="alert alert-info w-100" showon="updatesource!:default[OR]minimum_stability!:4" /> + diff --git a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php new file mode 100644 index 0000000000000..a705549b7a54c --- /dev/null +++ b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php @@ -0,0 +1,176 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Administrator\Model; + +use Joomla\CMS\Access\Access; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; +use Joomla\CMS\Mail\MailTemplate; +use Joomla\CMS\MVC\Model\BaseDatabaseModel; +use Joomla\CMS\Table\Asset; +use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Version; +use Joomla\Database\ParameterType; +use Joomla\Registry\Registry; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Joomla! Notification Model + * + * @internal + * @since __DEPLOY_VERSION__ + */ +final class NotificationModel extends BaseDatabaseModel +{ + public function sendNotification($type, $oldVersion): void + { + $params = ComponentHelper::getParams('com_joomlaupdate'); + + // Load the parameters. + $specificEmail = $params->get('auto_update_email'); + + // Let's find out the email addresses to notify + $superUsers = []; + + if (!empty($specificEmail)) { + $superUsers = $this->getSuperUsers($specificEmail); + } + + if (empty($superUsers)) { + $superUsers = $this->getSuperUsers(); + } + + if (empty($superUsers)) { + throw new \RuntimeException(); + } + + $app = Factory::getApplication(); + $jLanguage = $app->getLanguage(); + $sitename = $app->get('sitename'); + $newVersion = (new Version())->getShortVersion(); + + $substitutions = [ + 'oldversion' => $oldVersion, + 'newversion' => $newVersion, + 'sitename' => $sitename, + 'url' => Uri::base(), + ]; + + // Send the emails to the Super Users + foreach ($superUsers as $superUser) { + $params = new Registry($superUser->params); + $jLanguage->load('com_joomlaupdate', JPATH_ADMINISTRATOR, 'en-GB', true, true); + $jLanguage->load('com_joomlaupdate', JPATH_ADMINISTRATOR, $params->get('admin_language', null), true, true); + + $mailer = new MailTemplate('com_joomlaupdate.update.' . $type, $jLanguage->getTag()); + $mailer->addRecipient($superUser->email); + $mailer->addTemplateData($substitutions); + $mailer->send(); + } + } + + /** + * Returns the Super Users email information. If you provide a comma separated $email list + * we will check that these emails do belong to Super Users and that they have not blocked + * system emails. + * + * @param null|string $email A list of Super Users to email + * + * @return array The list of Super User emails + * + * @since __DEPLOY_VERSION__ + */ + private function getSuperUsers($email = null): array + { + $db = $this->getDatabase(); + $emails = []; + + // Convert the email list to an array + if (!empty($email)) { + $temp = explode(',', $email); + + foreach ($temp as $entry) { + $emails[] = trim($entry); + } + + $emails = array_unique($emails); + } + + // Get a list of groups which have Super User privileges + $ret = []; + + try { + $rootId = (new Asset($db))->getRootId(); + $rules = Access::getAssetRules($rootId)->getData(); + $rawGroups = $rules['core.admin']->getData(); + $groups = []; + + if (empty($rawGroups)) { + return $ret; + } + + foreach ($rawGroups as $g => $enabled) { + if ($enabled) { + $groups[] = $g; + } + } + + if (empty($groups)) { + return $ret; + } + } catch (\Exception $exc) { + return $ret; + } + + // Get the user IDs of users belonging to the SA groups + try { + $query = $db->getQuery(true) + ->select($db->quoteName('user_id')) + ->from($db->quoteName('#__user_usergroup_map')) + ->whereIn($db->quoteName('group_id'), $groups); + + $db->setQuery($query); + $userIDs = $db->loadColumn(0); + + if (empty($userIDs)) { + return $ret; + } + } catch (\Exception $exc) { + return $ret; + } + + // Get the user information for the Super Administrator users + try { + $query = $db->getQuery(true) + ->select($db->quoteName(['id', 'username', 'email', 'params'])) + ->from($db->quoteName('#__users')) + ->whereIn($db->quoteName('id'), $userIDs) + ->where($db->quoteName('block') . ' = 0') + ->where($db->quoteName('sendEmail') . ' = 1'); + + if (!empty($emails)) { + $lowerCaseEmails = array_map('strtolower', $emails); + $query->whereIn('LOWER(' . $db->quoteName('email') . ')', $lowerCaseEmails, ParameterType::STRING); + } + + $db->setQuery($query); + $ret = $db->loadObjectList(); + } catch (\Exception) { + return $ret; + } + + return $ret; + } + +} diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 5f9d614377ed4..ba432f25a6d85 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -101,9 +101,9 @@ COM_JOOMLAUPDATE_UPDATE_LOG_UNINSTALL_EXTENSIONS="Uninstalling extensions" COM_JOOMLAUPDATE_UPDATE_LOG_UPLOAD="Uploading update file" COM_JOOMLAUPDATE_UPDATE_LOG_URL="Downloading update file from %s." COM_JOOMLAUPDATE_UPDATE_LOGGING_TEST_FAIL="Logging does not work. Make sure the log folder is writable, and try again. The logging test failed with message: %s" -COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site has been successfully automatically updated from {CURVERSION} to {NEWVERSION}.\nPlease check your site for any unexpected behavior or malfunctions.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and the installation of such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" +COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site has been successfully automatically updated from {OLDVERSION} to {NEWVERSION}.\nPlease check your site for any unexpected behavior or malfunctions.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and the installation of such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT="Joomla! update failed for {SITENAME} – {URL}" -COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {CURVERSION} to {NEWVERSION}.\nPlease check the logfile of com_joomlaupdate for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile of com_joomlaupdate for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! successfully updated at {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATING_HEAD="Update in progress" COM_JOOMLAUPDATE_UPDATING_INPROGRESS="Please wait; Joomla is being updated. This may take a while." diff --git a/api/components/com_joomlaupdate/src/Controller/NotificationController.php b/api/components/com_joomlaupdate/src/Controller/NotificationController.php new file mode 100644 index 0000000000000..67165041b03f7 --- /dev/null +++ b/api/components/com_joomlaupdate/src/Controller/NotificationController.php @@ -0,0 +1,191 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Api\Controller; + +use Joomla\CMS\Language\Text; +use Joomla\Component\Joomlaupdate\Api\View\Updates\JsonapiView; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * The updates controller + * + * @since __DEPLOY_VERSION__ + */ +class NotificationController extends BaseController +{ + /** + * The content type of the item. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $contentType = 'notification'; + + /** + * The default view for the display method. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $default_view = 'notification'; + + /** + * Send fail notification to configured super users + * + * @return NotificationController For chaining + */ + public function failed() + { + $this->validateUpdateToken(); + + $fromVersion = $this->input->json->getString('fromVersion', null); + + $view = $this->prepareView(); + + $view->notification('failed', $fromVersion); + + return $this; + } + + /** + * Send success notification to configured super users + * + * @return NotificationController + * + * @since __DEPLOY_VERSION__ + */ + public function success() + { +// $this->validateUpdateToken(); + + $fromVersion = $this->input->json->getString('fromVersion', null); + + $view = $this->prepareView(); + + $view->notification('success', $fromVersion); + + return $this; + } + + /** + * Generic method to prepare the view + * + * @return JsonapiView The prepared view + */ + protected function prepareView() + { + $viewType = $this->app->getDocument()->getType(); + $viewName = $this->input->get('view', $this->default_view); + $viewLayout = $this->input->get('layout', 'default', 'string'); + + try { + /** @var JsonApiView $view */ + $view = $this->getView( + $viewName, + $viewType, + '', + ['base_path' => $this->basePath, 'layout' => $viewLayout, 'contentType' => $this->contentType] + ); + } catch (\Exception $e) { + throw new \RuntimeException($e->getMessage()); + } + + /** @var UpdateModel $model */ + $model = $this->getModel('Notification', 'Administrator', ['ignore_request' => true, 'state' => $this->modelState]); + + if (!$model) { + throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_MODEL_CREATE')); + } + + // Push the model into the view (as default) + $view->setModel($model, true); + + $view->setDocument($this->app->getDocument()); + + return $view; + } + + /** + * Basic display of an item view. We don't allow this + * + * @param integer $id The primary key to display. Leave empty if you want to retrieve data from the request + * + * @return static A \JControllerLegacy object to support chaining. + * + * @since __DEPLOY_VERSION__ + */ + public function displayItem($id = null) + { + throw new \RuntimeException('Not implemented', 501); + } + + /** + * List view amended to add filtering of data. We don't allow this + * + * @return static A BaseController object to support chaining. + * + * @since __DEPLOY_VERSION__ + */ + public function displayList() + { + throw new \RuntimeException('Not implemented', 501); + } + + /** + * Removes an item. + * + * @param integer $id The primary key to delete item. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function delete($id = null) + { + throw new \RuntimeException('Not implemented', 501); + } + + /** + * Method to check if you can edit an existing record. + * + * We don't allow editing from API (yet?) + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key; default is id. + * + * @return boolean + * + * @since __DEPLOY_VERSION__ + */ + protected function allowEdit($data = [], $key = 'id') + { + return false; + } + + /** + * Method to check if you can add a new record. + * + * We don't allow adding from API + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since __DEPLOY_VERSION__ + */ + protected function allowAdd($data = []) + { + return false; + } +} diff --git a/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php new file mode 100644 index 0000000000000..8932719efa51c --- /dev/null +++ b/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php @@ -0,0 +1,59 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Joomlaupdate\Api\View\Notification; + +use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; +use Joomla\CMS\Uri\Uri; +use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; +use Tobscure\JsonApi\Resource; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * The notification view + * + * @since __DEPLOY_VERSION__ + */ +class JsonapiView extends BaseApiView +{ + /** + * Generates the health check output + * + * @return string The rendered data + * + * @since __DEPLOY_VERSION__ + */ + public function notification($type, $oldVersion) + { + /** + * @var UpdateModel $model + */ + $model = $this->getModel(); + $success = true; + + try { + // Perform the finalization action + $model->sendNotification($type, $oldVersion); + } catch (\Throwable $e) { + $success = false; + } + + $element = (new Resource((object) ['success' => $success, 'id' => $type], $this->serializer)) + ->fields(['notification' => ['success']]); + + $this->getDocument()->setData($element); + $this->getDocument()->addLink('self', Uri::current()); + + return $this->getDocument()->render(); + } +} diff --git a/installation/sql/mysql/supports.sql b/installation/sql/mysql/supports.sql index ee2762809f088..25acb631c3ffa 100644 --- a/installation/sql/mysql/supports.sql +++ b/installation/sql/mysql/supports.sql @@ -416,8 +416,8 @@ INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subjec ('com_users.massmail.mail', 'com_users', '', 'COM_USERS_MASSMAIL_MAIL_SUBJECT', 'COM_USERS_MASSMAIL_MAIL_BODY', '', '', '{"tags":["subject","body","subjectprefix","bodysuffix"]}'), ('com_users.password_reset', 'com_users', '', 'COM_USERS_EMAIL_PASSWORD_RESET_SUBJECT', 'COM_USERS_EMAIL_PASSWORD_RESET_BODY', '', '', '{"tags":["name","email","sitename","link_text","link_html","token"]}'), ('com_users.reminder', 'com_users','', 'COM_USERS_EMAIL_USERNAME_REMINDER_SUBJECT', 'COM_USERS_EMAIL_USERNAME_REMINDER_BODY', '', '', '{"tags":["name","username","sitename","email","link_text","link_html"]}'), -('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), -('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), ('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'), ('plg_user_joomla.mail', 'plg_user_joomla', '', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_SUBJECT', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_BODY', '', '', '{"tags":["name","sitename","url","username","password","email"]}'), ('com_actionlogs.notification', 'com_actionlogs', '', 'COM_ACTIONLOGS_EMAIL_SUBJECT', 'COM_ACTIONLOGS_EMAIL_BODY', 'COM_ACTIONLOGS_EMAIL_HTMLBODY', '', '{"tags":["messages","message","date","extension","username"]}'), diff --git a/installation/sql/postgresql/supports.sql b/installation/sql/postgresql/supports.sql index 1eb4ea5ddfe43..4c438e10cd14e 100644 --- a/installation/sql/postgresql/supports.sql +++ b/installation/sql/postgresql/supports.sql @@ -427,8 +427,8 @@ INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subjec ('com_users.massmail.mail', 'com_users', '', 'COM_USERS_MASSMAIL_MAIL_SUBJECT', 'COM_USERS_MASSMAIL_MAIL_BODY', '', '', '{"tags":["subject","body","subjectprefix","bodysuffix"]}'), ('com_users.password_reset', 'com_users', '', 'COM_USERS_EMAIL_PASSWORD_RESET_SUBJECT', 'COM_USERS_EMAIL_PASSWORD_RESET_BODY', '', '', '{"tags":["name","email","sitename","link_text","link_html","token"]}'), ('com_users.reminder', 'com_users', '', 'COM_USERS_EMAIL_USERNAME_REMINDER_SUBJECT', 'COM_USERS_EMAIL_USERNAME_REMINDER_BODY', '', '', '{"tags":["name","username","sitename","email","link_text","link_html"]}'), -('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), -('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url"]}'), +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), ('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'), ('plg_user_joomla.mail', 'plg_user_joomla', '', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_SUBJECT', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_BODY', '', '', '{"tags":["name","sitename","url","username","password","email"]}'), ('com_actionlogs.notification', 'com_actionlogs', '', 'COM_ACTIONLOGS_EMAIL_SUBJECT', 'COM_ACTIONLOGS_EMAIL_BODY', 'COM_ACTIONLOGS_EMAIL_HTMLBODY', '', '{"tags":["messages","message","date","extension","username"]}'), diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index 137089abdcefb..57f27e91ab0d6 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -60,6 +60,8 @@ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void new Route(['GET'], 'v1/joomlaupdate/getUpdate', 'updates.getUpdate', [], $defaults), new Route(['POST'], 'v1/joomlaupdate/prepareUpdate', 'updates.prepareUpdate', [], $defaults), new Route(['POST'], 'v1/joomlaupdate/finalizeUpdate', 'updates.finalizeUpdate', [], $defaults), + new Route(['GET'], 'v1/joomlaupdate/notificationSuccess', 'notification.success', [], $defaults), + new Route(['POST'], 'v1/joomlaupdate/notificationFail', 'notification.fail', [], $defaults), ]; $router->addRoutes($routes); From 582016d1a4da33c21687de657d40011dfe017a4a Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 15 Mar 2025 22:39:56 +0100 Subject: [PATCH 079/130] Rename auto update => automated update --- .../com_joomlaupdate/src/Controller/UpdateController.php | 2 +- .../components/com_joomlaupdate/src/Model/UpdateModel.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 0f1382ca0157a..68a00fac93c3e 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -716,7 +716,7 @@ public function ajax() } /** - * Fetch and report health status of the auto update in \JSON format, for AJAX requests + * Fetch and report health status of the automated update in \JSON format, for AJAX requests * * @return void * diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index 869b6499ef85b..9c9106c4fdf4a 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -485,7 +485,7 @@ public function updateLastHealthCheck() } /** - * Get the latest version for the auto update + * Get the latest version for the automated update * * @return string|null * From d13e36285fdb265f3e1e1a0f25d8a09fffc7e5aa Mon Sep 17 00:00:00 2001 From: Benjamin Trenkle Date: Sat, 15 Mar 2025 22:44:55 +0100 Subject: [PATCH 080/130] Automated update => automated updates --- administrator/components/com_joomlaupdate/config.xml | 4 ++-- .../com_joomlaupdate/src/Controller/UpdateController.php | 2 +- administrator/language/en-GB/com_joomlaupdate.ini | 4 ++-- .../language/en-GB/guidedtours.joomla_whatsnew_5_3.ini | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index ecc5ca046f540..4723a171724be 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -112,9 +112,9 @@ showon="updatesource:default[AND]minimum_stability:4[AND]autoupdate:1" /> diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 68a00fac93c3e..1dd3405032639 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -716,7 +716,7 @@ public function ajax() } /** - * Fetch and report health status of the automated update in \JSON format, for AJAX requests + * Fetch and report health status of the automated updates in \JSON format, for AJAX requests * * @return void * diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 8ced7f4e47bcd..a39971d311485 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -9,7 +9,7 @@ COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Successful unregistered from aut COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from autoupdate service: %s (%d)" COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." -COM_JOOMLAUPDATE_CONFIG_AUTO_UPDATE_DISABLED_LABEL=" Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." +COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_DISABLED_LABEL=" Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_LABEL="Automated Updates" COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_DESC="Automatically update Joomla to the latest version when it is available." COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_LABEL="Automated Update" @@ -20,7 +20,7 @@ COM_JOOMLAUPDATE_CONFIG_SOURCES_DESC="Configure where Joomla gets its update inf COM_JOOMLAUPDATE_CONFIG_SOURCES_LABEL="Update Source" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM="Custom URL" COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_LABEL="Last Checked" -COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_DESC="The last time the automated update server could reach this site. If this date is too old, something is wrong with the automated update and you should re-initiate the process by re-saving the configuration." +COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_DESC="The last time the automated updates server could reach this site. If this date is too old, something is wrong with the automated updates and you should re-initiate the process by re-saving the configuration." COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM_ERROR="The custom URL field is empty." COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_DEFAULT="Default" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_LABEL="Update Channel" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini index b9a4ab376d870..85053379e5e3f 100644 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini @@ -3,5 +3,5 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION="

Welcome to Joomla 5.3!

\"Display

Automated Updates are here!

Joomla! 5.3 now supports automated updates for better security and performance.

Enable your automated updates now

Stay safe and secure!

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION="

Welcome to Joomla 5.3!

\"Display

Automated Updates are here!

Joomla! 5.3 now supports automated updates for better security and performance.

Enable your automated updates now

Stay safe and secure!

" COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE="What’s New in Joomla 5.3!" From 730b0ae91d667e895a4b6c103be4bb204a1b439e Mon Sep 17 00:00:00 2001 From: hleithner Date: Sat, 15 Mar 2025 22:44:34 +0100 Subject: [PATCH 081/130] Fixed notification --- administrator/components/com_joomlaupdate/config.xml | 6 +++--- administrator/language/en-GB/com_joomlaupdate.ini | 2 ++ .../src/Controller/NotificationController.php | 2 +- .../webservices/joomlaupdate/src/Extension/Joomlaupdate.php | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index 9a0fefe4800d8..f7d02c27f4fb6 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -120,10 +120,10 @@ /> diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 97df5e0976f92..d01ecf60e0a57 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -13,6 +13,8 @@ COM_JOOMLAUPDATE_CONFIG_AUTO_UPDATE_DISABLED_LABEL="validateUpdateToken(); + $this->validateUpdateToken(); $fromVersion = $this->input->json->getString('fromVersion', null); diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index 22accf9fae868..313da605ffc54 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -60,8 +60,8 @@ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void new Route(['GET'], 'v1/joomlaupdate/getUpdate', 'updates.getUpdate', [], $defaults), new Route(['POST'], 'v1/joomlaupdate/prepareUpdate', 'updates.prepareUpdate', [], $defaults), new Route(['POST'], 'v1/joomlaupdate/finalizeUpdate', 'updates.finalizeUpdate', [], $defaults), - new Route(['GET'], 'v1/joomlaupdate/notificationSuccess', 'notification.success', [], $defaults), - new Route(['POST'], 'v1/joomlaupdate/notificationFail', 'notification.fail', [], $defaults), + new Route(['POST'], 'v1/joomlaupdate/notificationSuccess', 'notification.success', [], $defaults), + new Route(['POST'], 'v1/joomlaupdate/notificationFailed', 'notification.failed', [], $defaults), ]; $router->addRoutes($routes); From 5a7de0d62386bf03be5bd8dbaf0e90e795bf4c34 Mon Sep 17 00:00:00 2001 From: hleithner Date: Sat, 15 Mar 2025 22:45:09 +0100 Subject: [PATCH 082/130] Fixed notification --- administrator/components/com_joomlaupdate/config.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index f7d02c27f4fb6..cb54a064c40be 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -121,8 +121,8 @@ From ecc2814dc1b08e79e91f334100e3c7087bc8dcd7 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 16 Mar 2025 12:25:19 +0100 Subject: [PATCH 083/130] Rename update SQL scripts --- .../updates/mysql/{5.3.0-2025-01-18.sql => 5.4.0-2025-03-16.sql} | 0 .../updates/mysql/{5.3.0-2025-03-15.sql => 5.4.0-2025-03-17.sql} | 0 .../postgresql/{5.3.0-2025-01-18.sql => 5.4.0-2025-03-16.sql} | 0 .../postgresql/{5.3.0-2025-03-15.sql => 5.4.0-2025-03-17.sql} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename administrator/components/com_admin/sql/updates/mysql/{5.3.0-2025-01-18.sql => 5.4.0-2025-03-16.sql} (100%) rename administrator/components/com_admin/sql/updates/mysql/{5.3.0-2025-03-15.sql => 5.4.0-2025-03-17.sql} (100%) rename administrator/components/com_admin/sql/updates/postgresql/{5.3.0-2025-01-18.sql => 5.4.0-2025-03-16.sql} (100%) rename administrator/components/com_admin/sql/updates/postgresql/{5.3.0-2025-03-15.sql => 5.4.0-2025-03-17.sql} (100%) diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-16.sql similarity index 100% rename from administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-01-18.sql rename to administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-16.sql diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-15.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql similarity index 100% rename from administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-15.sql rename to administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-16.sql similarity index 100% rename from administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-01-18.sql rename to administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-16.sql diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-15.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql similarity index 100% rename from administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-15.sql rename to administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql From 892fef3c6382dc80efc05fbb77109cfd046fb4b3 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 16 Mar 2025 12:38:36 +0100 Subject: [PATCH 084/130] Revert guided tours update SQL changes --- .../com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql | 9 ++------- .../sql/updates/postgresql/5.3.0-2025-03-14.sql | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql index 5a9a4f6981ac4..2eedbb010e52d 100644 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql +++ b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql @@ -5,11 +5,6 @@ INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `publ ('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-3', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0); INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'center', '', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 FROM `#__guidedtours` - WHERE `uid` = 'joomla-whatsnew-5-3'; - -INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 - FROM `#__guidedtours` - WHERE `uid` = 'joomla-whatsnew-5-3'; + WHERE `uid` = 'joomla-whatsnew-5-3'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql index 85624c9abbbe9..cfb58259717f7 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql @@ -5,11 +5,6 @@ INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "publ ('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-3', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0); INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'center', '', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 FROM "#__guidedtours" - WHERE "uid" = 'joomla-whatsnew-5-3'; - -INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 - FROM "#__guidedtours" - WHERE "uid" = 'joomla-whatsnew-5-3'; + WHERE "uid" = 'joomla-whatsnew-5-3'; From 101735b4abbae00fe79e2960c90a64717a0ae6b1 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 16 Mar 2025 12:39:49 +0100 Subject: [PATCH 085/130] Move image for guided tours to 5.4 --- .../images/{5_3 => 5_4}/automated-updates.jpg | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename build/media_source/com_guidedtours/images/{5_3 => 5_4}/automated-updates.jpg (100%) diff --git a/build/media_source/com_guidedtours/images/5_3/automated-updates.jpg b/build/media_source/com_guidedtours/images/5_4/automated-updates.jpg similarity index 100% rename from build/media_source/com_guidedtours/images/5_3/automated-updates.jpg rename to build/media_source/com_guidedtours/images/5_4/automated-updates.jpg From 92017a743015d189e51958993d490297cff52a2a Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 16 Mar 2025 12:43:51 +0100 Subject: [PATCH 086/130] Revert guided tours 5.3 language file changes --- .../language/en-GB/guidedtours.joomla_whatsnew_5_3.ini | 2 +- .../en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini index 85053379e5e3f..279928d33f031 100644 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini @@ -3,5 +3,5 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION="

Welcome to Joomla 5.3!

\"Display

Automated Updates are here!

Joomla! 5.3 now supports automated updates for better security and performance.

Enable your automated updates now

Stay safe and secure!

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION="

Welcome to Joomla 5.3!

Guided Tours Updates

Guided Tours now has its own API. Joomla API Documentation

Stay tuned for other new enhancements coming soon!

\"The

Core Updates

Organize Files in their Own Location

Now you can see and select your stored/uploaded documents directly from the Media Manager. Find more information in the Joomla Community Magazine.

View Scheduled Task History

You now have the ability to view execution information directly in the backend without having to access log files. Look for the Execution History button located in the Scheduled Tasks page.

Other Enhancements and Fixes

  • Template Override Plugin Comparison - adds compare functionality to plugin overrides
  • Tag Alias Lookup Fixed - now instead of showing the tag id number in the URL the tag name is shown
" COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE="What’s New in Joomla 5.3!" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini index b474b42b47738..fe8788b793d8c 100644 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini @@ -3,7 +3,5 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_DESCRIPTION="

Joomla 5.3 Full Release Notes

View the full release notes on joomla.org


Help and Information

Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.

" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_1_TITLE="More Information and Help" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION="

More mentionable features

Guided Tours Updates

Guided Tours now has its own API. Joomla API Documentation

Stay tuned for other new enhancements coming soon!

\"The

Core Updates

Organize Files in their Own Location

Now you can see and select your stored/uploaded documents directly from the Media Manager. Find more information in the Joomla Community Magazine.

View Scheduled Task History

You now have the ability to view execution information directly in the backend without having to access log files. Look for the Execution History button located in the Scheduled Tasks page.

Other Enhancements and Fixes

  • Template Override Plugin Comparison - adds compare functionality to plugin overrides
  • Tag Alias Lookup Fixed - now instead of showing the tag id number in the URL the tag name is shown
" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE="More mentionable features" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION="

Joomla 5.3 Full Release Notes

View the full release notes on joomla.org


Help and Information

Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE="More Information and Help" From 7c80d91cea62c5cb2f22e8b654cd2be49d38e2ad Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 16 Mar 2025 12:48:46 +0100 Subject: [PATCH 087/130] Change postinstall message condition to 5.4.0 --- .../components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql | 2 +- .../com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql | 2 +- installation/sql/mysql/supports.sql | 2 +- installation/sql/postgresql/supports.sql | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql index b202f3249483c..54c1d56d149ef 100644 --- a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql +++ b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql @@ -1,3 +1,3 @@ -- add post-installation messaged for automated updates INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) -SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.3.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; +SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql index 8f4e9b2a50afc..0b677991990c6 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql @@ -1,3 +1,3 @@ -- add post-installation messaged for automated updates INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") -SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.3.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; +SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; diff --git a/installation/sql/mysql/supports.sql b/installation/sql/mysql/supports.sql index 5b9dd8a8c246d..2722075b7a064 100644 --- a/installation/sql/mysql/supports.sql +++ b/installation/sql/mysql/supports.sql @@ -279,7 +279,7 @@ SELECT `extension_id`, 'PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_TITLE', INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) SELECT `extension_id`, 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_TITLE', 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_BODY', 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_ACTION', 'com_users', 1, 'action', 'admin://components/com_users/postinstall/multifactorauth.php', 'com_users_postinstall_mfa_action', 'admin://components/com_users/postinstall/multifactorauth.php', 'com_users_postinstall_mfa_condition', '4.2.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) -SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.3.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; +SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; -- -------------------------------------------------------- diff --git a/installation/sql/postgresql/supports.sql b/installation/sql/postgresql/supports.sql index 387add47f692e..712b5679c2345 100644 --- a/installation/sql/postgresql/supports.sql +++ b/installation/sql/postgresql/supports.sql @@ -290,7 +290,7 @@ SELECT "extension_id", 'PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_TITLE', INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") SELECT "extension_id", 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_TITLE', 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_BODY', 'COM_USERS_POSTINSTALL_MULTIFACTORAUTH_ACTION', 'com_users', 1, 'action', 'admin://components/com_users/postinstall/multifactorauth.php', 'com_users_postinstall_mfa_action', 'admin://components/com_users/postinstall/multifactorauth.php', 'com_users_postinstall_mfa_condition', '4.2.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") -SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.3.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; +SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; -- -- Table structure for table `#__ucm_base` From f2da310a05d5d3708e90d7f461bac760265bf951 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 16 Mar 2025 12:53:26 +0100 Subject: [PATCH 088/130] Change postinstall message to 5.4 --- administrator/language/en-GB/com_joomlaupdate.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index a39971d311485..a4a264307805f 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -64,7 +64,7 @@ COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_REASON_PHP="Your PHP version \"%1$s\" is COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_TITLE="This site can't be updated to Joomla %1$s" COM_JOOMLAUPDATE_OVERVIEW="Joomla Update" COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION="Active Automated Updates" -COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION="Joomla 5.3 now supports Automated updates for better security and performance. Select \"Activate Automated Updates\" to stay up to date effortlessly!" +COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION="Joomla 5.4 now supports Automated updates for better security and performance. Select \"Activate Automated Updates\" to stay up to date effortlessly!" COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE="Automated Joomla Updates" COM_JOOMLAUPDATE_PREUPDATE_CHECK_CAPTION="Server settings to check before update." COM_JOOMLAUPDATE_PREUPDATE_CHECK_COMPLETED_YOU_HAVE_DANGEROUS_PLUGINS="There are plugins installed and enabled that could interfere with the Joomla update and result in a failed update that leaves the site inaccessible.

You are strongly advised to update, disable or uninstall these plugins before upgrading." From afe385346650d60aab0fe9bfd23083810082ccdb Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 16 Mar 2025 13:32:26 +0100 Subject: [PATCH 089/130] Add guided tours what's new in 5.4 --- .../com_admin/sql/updates/mysql/5.4.0-2025-03-18.sql | 10 ++++++++++ .../sql/updates/postgresql/5.4.0-2025-03-18.sql | 10 ++++++++++ .../language/en-GB/guidedtours.joomla_whatsnew_5_4.ini | 7 +++++++ .../en-GB/guidedtours.joomla_whatsnew_5_4_steps.ini | 7 +++++++ 4 files changed, 34 insertions(+) create mode 100644 administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-18.sql create mode 100644 administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-18.sql create mode 100644 administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini create mode 100644 administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4_steps.ini diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-18.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-18.sql new file mode 100644 index 0000000000000..1496d0dcec732 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-18.sql @@ -0,0 +1,10 @@ +-- disable autostart for the previous tour +UPDATE `#__guidedtours` SET `autostart` = 0 WHERE `uid` = 'joomla-whatsnew-5-3'; + +INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `published`, `language`, `note`, `access`, `uid`, `autostart`, `created`, `created_by`, `modified`, `modified_by`) VALUES +('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-4', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0); + +INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 + FROM `#__guidedtours` + WHERE `uid` = 'joomla-whatsnew-5-4'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-18.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-18.sql new file mode 100644 index 0000000000000..9220b15aa3a61 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-18.sql @@ -0,0 +1,10 @@ +-- disable autostart for the previous tour +UPDATE "#__guidedtours" SET "autostart" = 0 WHERE "uid" = 'joomla-whatsnew-5-3'; + +INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "published", "language", "note", "access", "uid", "autostart", "created", "created_by", "modified", "modified_by") VALUES +('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-4', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0); + +INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 + FROM "#__guidedtours" + WHERE "uid" = 'joomla-whatsnew-5-4'; diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini new file mode 100644 index 0000000000000..177c1cf370b3e --- /dev/null +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2025 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION="

Welcome to Joomla 5.4!

\"Display

Automated Updates are here!

Joomla! 5.4 now supports automated updates for better security and performance.

Enable your automated updates now

Stay safe and secure!

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE="What’s New in Joomla 5.4!" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4_steps.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4_steps.ini new file mode 100644 index 0000000000000..6ee83abbbb253 --- /dev/null +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4_steps.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2025 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION="

Joomla 5.4 Full Release Notes

View the full release notes on joomla.org


Help and Information

Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE="More Information and Help" From 04c27fd5772e62158b3986c514a75c8d45cf96db Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sun, 16 Mar 2025 14:48:49 +0100 Subject: [PATCH 090/130] Apply suggestions from code review Thanks @brianteeman Co-authored-by: Brian Teeman --- administrator/language/en-GB/com_joomlaupdate.ini | 6 +++--- administrator/language/en-GB/plg_quickicon_autoupdate.ini | 6 +++--- .../language/en-GB/plg_quickicon_autoupdate.sys.ini | 4 ++-- .../com_joomlaupdate/src/View/Updates/JsonapiView.php | 2 +- plugins/quickicon/autoupdate/autoupdate.xml | 2 +- plugins/quickicon/autoupdate/services/provider.php | 2 +- plugins/webservices/joomlaupdate/joomlaupdate.xml | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index a4a264307805f..514bf29e5393b 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -3,9 +3,9 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS="Successful registered to autoupdate service" +COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS="Registered to autoupdate service" COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR="Error while registering to autoupdate service: %s (%d)" -COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Successful unregistered from autoupdate service" +COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Unregistered from autoupdate service" COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from autoupdate service: %s (%d)" COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." @@ -63,7 +63,7 @@ COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_REASON_DATABASE="Your %1$s version \"%2$s COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_REASON_PHP="Your PHP version \"%1$s\" is lower than \"%2$s\"." COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_TITLE="This site can't be updated to Joomla %1$s" COM_JOOMLAUPDATE_OVERVIEW="Joomla Update" -COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION="Active Automated Updates" +COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION="Activate Automated Updates" COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION="Joomla 5.4 now supports Automated updates for better security and performance. Select \"Activate Automated Updates\" to stay up to date effortlessly!" COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE="Automated Joomla Updates" COM_JOOMLAUPDATE_PREUPDATE_CHECK_CAPTION="Server settings to check before update." diff --git a/administrator/language/en-GB/plg_quickicon_autoupdate.ini b/administrator/language/en-GB/plg_quickicon_autoupdate.ini index e012f1bbd4a95..bb42d09d464f8 100644 --- a/administrator/language/en-GB/plg_quickicon_autoupdate.ini +++ b/administrator/language/en-GB/plg_quickicon_autoupdate.ini @@ -3,13 +3,13 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Auto Update Health Notification" -PLG_QUICKICON_AUTOUPDATE_CHECKING="Checking Auto Update …" +PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Automated Update Health Notification" +PLG_QUICKICON_AUTOUPDATE_CHECKING="Checking Automated Update …" PLG_QUICKICON_AUTOUPDATE_DISABLED="Automated Updates are disabled." PLG_QUICKICON_AUTOUPDATE_ERROR="Unknown Health status …" PLG_QUICKICON_AUTOUPDATE_GROUP_DESC="The group of this plugin (this value is compared with the group value used in Quick Icons modules to inject icons)." PLG_QUICKICON_AUTOUPDATE_GROUP_LABEL="Group" PLG_QUICKICON_AUTOUPDATE_OK="Automated Updates working." PLG_QUICKICON_AUTOUPDATE_OUTDATED="Automated Updates connection broken." -PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of auto updates and notifies you when you visit the Home Dashboard page." +PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of automated updates and notifies you when you visit the Home Dashboard page." diff --git a/administrator/language/en-GB/plg_quickicon_autoupdate.sys.ini b/administrator/language/en-GB/plg_quickicon_autoupdate.sys.ini index cdcadc5c384f4..6ae79925aac67 100644 --- a/administrator/language/en-GB/plg_quickicon_autoupdate.sys.ini +++ b/administrator/language/en-GB/plg_quickicon_autoupdate.sys.ini @@ -3,5 +3,5 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Auto Update Health Notification" -PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of auto updates and notifies you when you visit the Home Dashboard page." +PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Automated Update Health Notification" +PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of automated updates and notifies you when you visit the Home Dashboard page." diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index 8573315306964..e5f66ebe4b1eb 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -4,7 +4,7 @@ * @package Joomla.API * @subpackage com_joomlaupdate * - * @copyright (C) 2024 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ diff --git a/plugins/quickicon/autoupdate/autoupdate.xml b/plugins/quickicon/autoupdate/autoupdate.xml index 8ed7cc372ff25..e54559280d51c 100644 --- a/plugins/quickicon/autoupdate/autoupdate.xml +++ b/plugins/quickicon/autoupdate/autoupdate.xml @@ -7,7 +7,7 @@ GNU General Public License version 2 or later; see LICENSE.txt admin@joomla.org www.joomla.org - 5.3.0 + 5.4.0 PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION Joomla\Plugin\Quickicon\Autoupdate diff --git a/plugins/quickicon/autoupdate/services/provider.php b/plugins/quickicon/autoupdate/services/provider.php index 99b431229e444..22860f95a0753 100644 --- a/plugins/quickicon/autoupdate/services/provider.php +++ b/plugins/quickicon/autoupdate/services/provider.php @@ -25,7 +25,7 @@ * * @return void * - * @since 4.0.0 + * @since __DEPLOY_VERSION__ */ public function register(Container $container) { diff --git a/plugins/webservices/joomlaupdate/joomlaupdate.xml b/plugins/webservices/joomlaupdate/joomlaupdate.xml index f6e11345e491d..1a32eb9915ad8 100644 --- a/plugins/webservices/joomlaupdate/joomlaupdate.xml +++ b/plugins/webservices/joomlaupdate/joomlaupdate.xml @@ -7,7 +7,7 @@ GNU General Public License version 2 or later; see LICENSE.txt admin@joomla.org www.joomla.org - 5.3.0 + 5.4.0 PLG_WEBSERVICES_JOOMLAUPDATE_XML_DESCRIPTION Joomla\Plugin\WebServices\Joomlaupdate From 88a3093ebf44fe3411d0da9b6628f01c5da61242 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Mon, 21 Apr 2025 09:40:34 +0200 Subject: [PATCH 091/130] implement code review suggestions --- administrator/components/com_joomlaupdate/config.xml | 2 +- .../com_joomlaupdate/src/Model/NotificationModel.php | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index 5ad97ef4a9fd3..e74251b5165ea 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -119,7 +119,7 @@ showon="updatesource!:default[OR]minimum_stability!:4" /> get('auto_update_email'); + $specificEmail = $params->get('automated_updates_email'); // Let's find out the email addresses to notify $superUsers = []; @@ -101,6 +102,10 @@ private function getSuperUsers($email = null): array $temp = explode(',', $email); foreach ($temp as $entry) { + if (!MailHelper::isEmailAddress(trim($entry))) { + continue; + } + $emails[] = trim($entry); } @@ -164,8 +169,7 @@ private function getSuperUsers($email = null): array $query->whereIn('LOWER(' . $db->quoteName('email') . ')', $lowerCaseEmails, ParameterType::STRING); } - $db->setQuery($query); - $ret = $db->loadObjectList(); + $ret = $db->setQuery($query)->loadObjectList(); } catch (\Exception) { return $ret; } From a1ba665493dce64cf072e7d8255af0ec1203d1ae Mon Sep 17 00:00:00 2001 From: David Jardin Date: Mon, 21 Apr 2025 10:37:28 +0200 Subject: [PATCH 092/130] Added CLI commands for registration and unregistraoitn --- .../src/Application/ConsoleApplication.php | 2 + .../AutomatedUpdatesRegisterCommand.php | 135 ++++++++++++++++++ .../AutomatedUpdatesUnregisterCommand.php | 135 ++++++++++++++++++ libraries/src/Uri/Uri.php | 6 + 4 files changed, 278 insertions(+) create mode 100644 libraries/src/Console/AutomatedUpdatesRegisterCommand.php create mode 100644 libraries/src/Console/AutomatedUpdatesUnregisterCommand.php diff --git a/libraries/src/Application/ConsoleApplication.php b/libraries/src/Application/ConsoleApplication.php index bb68e31ef43d4..255412ca1d353 100644 --- a/libraries/src/Application/ConsoleApplication.php +++ b/libraries/src/Application/ConsoleApplication.php @@ -298,6 +298,8 @@ protected function getDefaultCommands(): array return array_merge( parent::getDefaultCommands(), [ + new Console\AutomatedUpdatesRegisterCommand(), + new Console\AutomatedUpdatesUnregisterCommand(), new Console\CleanCacheCommand(), new Console\CheckUpdatesCommand(), new Console\CheckJoomlaUpdatesCommand(), diff --git a/libraries/src/Console/AutomatedUpdatesRegisterCommand.php b/libraries/src/Console/AutomatedUpdatesRegisterCommand.php new file mode 100644 index 0000000000000..974fc811e0dab --- /dev/null +++ b/libraries/src/Console/AutomatedUpdatesRegisterCommand.php @@ -0,0 +1,135 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Console; + +use Joomla\CMS\Application\ConsoleApplication; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; +use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; +use Joomla\Console\Command\AbstractCommand; +use Joomla\Uri\UriHelper; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Console command for managing the update channel for Joomla + * + * @since __DEPLOY_VERSION__ + */ +class AutomatedUpdatesRegisterCommand extends AbstractCommand +{ + /** + * The default command name + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected static $defaultName = 'core:autoupdate:register'; + + /** + * SymfonyStyle Object + * + * @var SymfonyStyle + * @since __DEPLOY_VERSION__ + */ + private $ioStyle; + + /** + * Initialise the command. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function configure(): void + { + $help = "%command.name% allows to register a site for the automated core update service. + \nUsage: php %command.full_name%"; + + $this->setDescription('Register the current site for the automated core update service.'); + $this->setHelp($help); + } + + /** + * Configures the IO + * + * @param InputInterface $input Console Input + * @param OutputInterface $output Console Output + * + * @return void + * + * @since __DEPLOY_VERSION__ + * + */ + private function configureIO(InputInterface $input, OutputInterface $output) + { + $this->ioStyle = new SymfonyStyle($input, $output); + } + + /** + * Internal function to execute the command. + * + * @param InputInterface $input The input to inject into the command. + * @param OutputInterface $output The output to inject into the command. + * + * @return integer The command exit code + * + * @since __DEPLOY_VERSION__ + */ + protected function doExecute(InputInterface $input, OutputInterface $output): int + { + $this->configureIO($input, $output); + + // Get live site parameter + $liveSite = $input->getOption('live-site'); + + /** @var ConsoleApplication $app */ + $app = $this->getApplication(); + $app->getLanguage()->load('com_joomlaupdate', JPATH_ADMINISTRATOR); + + // Check that the URL is provided + if (empty($liveSite)) { + $this->ioStyle->writeln('ERROR: Missing --live-site option'); + + return Command::FAILURE; + } + + // Parse URL and check existence of parts + $urlParts = UriHelper::parse_url($liveSite); + + if (empty($urlParts['scheme']) || empty($urlParts['host'])) { + $this->ioStyle->writeln( + 'ERROR: Incomplete --live-site provided; provide scheme and host' + ); + + return Command::FAILURE; + } + + // Run registration + /** @var UpdateModel $updateModel */ + $updateModel = $app + ->bootComponent('com_joomlaupdate') + ->getMVCFactory($app) + ->createModel('Update', 'Administrator'); + + $result = $updateModel->changeAutoUpdateRegistration(AutoupdateRegisterState::Subscribe); + + if ($result === false) { + return Command::FAILURE; + } + + return Command::SUCCESS; + } +} diff --git a/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php b/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php new file mode 100644 index 0000000000000..a51f7fcc5b64e --- /dev/null +++ b/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php @@ -0,0 +1,135 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Console; + +use Joomla\CMS\Application\ConsoleApplication; +use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; +use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; +use Joomla\Console\Command\AbstractCommand; +use Joomla\Uri\UriHelper; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Console command for managing the update channel for Joomla + * + * @since __DEPLOY_VERSION__ + */ +class AutomatedUpdatesUnregisterCommand extends AbstractCommand +{ + /** + * The default command name + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected static $defaultName = 'core:autoupdate:unregister'; + + /** + * SymfonyStyle Object + * + * @var SymfonyStyle + * @since __DEPLOY_VERSION__ + */ + private $ioStyle; + + /** + * Initialise the command. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function configure(): void + { + $help = "%command.name% allows to unregister a site from the automated core update service. + \nUsage: php %command.full_name%"; + + $this->setDescription('Unregister the current site for the unautomated core update service.'); + $this->setHelp($help); + } + + /** + * Configures the IO + * + * @param InputInterface $input Console Input + * @param OutputInterface $output Console Output + * + * @return void + * + * @since __DEPLOY_VERSION__ + * + */ + private function configureIO(InputInterface $input, OutputInterface $output) + { + $this->ioStyle = new SymfonyStyle($input, $output); + } + + /** + * Internal function to execute the command. + * + * @param InputInterface $input The input to inject into the command. + * @param OutputInterface $output The output to inject into the command. + * + * @return integer The command exit code + * + * @since __DEPLOY_VERSION__ + */ + protected function doExecute(InputInterface $input, OutputInterface $output): int + { + $this->configureIO($input, $output); + + // Get live site parameter + $liveSite = $input->getOption('live-site'); + + /** @var ConsoleApplication $app */ + $app = $this->getApplication(); + $app->getLanguage()->load('com_joomlaupdate', JPATH_ADMINISTRATOR); + + // Check that the URL is provided + if (empty($liveSite)) { + $this->ioStyle->writeln('ERROR: Missing --live-site option'); + + return Command::FAILURE; + } + + // Parse URL and check existence of parts + $urlParts = UriHelper::parse_url($liveSite); + + if (empty($urlParts['scheme']) || empty($urlParts['host'])) { + $this->ioStyle->writeln( + 'ERROR: Incomplete --live-site provided; provide scheme and host' + ); + + return Command::FAILURE; + } + + // Run registration + /** @var UpdateModel $updateModel */ + $updateModel = $app + ->bootComponent('com_joomlaupdate') + ->getMVCFactory($app) + ->createModel('Update', 'Administrator'); + + $result = $updateModel->changeAutoUpdateRegistration(AutoupdateRegisterState::Unsubscribe); + + if ($result === false) { + return Command::FAILURE; + } + + return Command::SUCCESS; + } +} diff --git a/libraries/src/Uri/Uri.php b/libraries/src/Uri/Uri.php index d4036e83a6ddb..0bcf641900c6c 100644 --- a/libraries/src/Uri/Uri.php +++ b/libraries/src/Uri/Uri.php @@ -145,6 +145,12 @@ public static function base($pathonly = false) if (\defined('JPATH_BASE') && \defined('JPATH_API') && JPATH_BASE == JPATH_API) { static::$base['path'] .= '/api'; } + } elseif (str_contains(PHP_SAPI, 'cli')) { + // In CLI mode, the site base path can not be derived from the script name; the static path has to be used + static::$base['prefix'] = $uri->toString(['scheme', 'host', 'port']); + static::$base['path'] = rtrim($uri->toString(['path']), '/\\'); + + return $pathonly === false ? static::$base['prefix'] . static::$base['path'] . '/' : static::$base['path']; } else { static::$base['prefix'] = $uri->toString(['scheme', 'host', 'port']); From d1274c954cf8b6d331f6b1e11cef5c702d86b5be Mon Sep 17 00:00:00 2001 From: David Jardin Date: Mon, 21 Apr 2025 12:29:58 +0200 Subject: [PATCH 093/130] Update libraries/src/Console/AutomatedUpdatesUnregisterCommand.php Co-authored-by: Brian Teeman --- libraries/src/Console/AutomatedUpdatesUnregisterCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php b/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php index a51f7fcc5b64e..65cad3948adf8 100644 --- a/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php +++ b/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php @@ -3,7 +3,7 @@ /** * Joomla! Content Management System * - * @copyright (C) 2020 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ From dcfd1acc723310d4fffc079f64b4d6173b3ff859 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Mon, 21 Apr 2025 12:30:05 +0200 Subject: [PATCH 094/130] Update libraries/src/Console/AutomatedUpdatesRegisterCommand.php Co-authored-by: Brian Teeman --- libraries/src/Console/AutomatedUpdatesRegisterCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/src/Console/AutomatedUpdatesRegisterCommand.php b/libraries/src/Console/AutomatedUpdatesRegisterCommand.php index 974fc811e0dab..d612950f051f3 100644 --- a/libraries/src/Console/AutomatedUpdatesRegisterCommand.php +++ b/libraries/src/Console/AutomatedUpdatesRegisterCommand.php @@ -3,7 +3,7 @@ /** * Joomla! Content Management System * - * @copyright (C) 2020 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ From 759d68442e3dfd9a5d9a6c77d75aa63b2b33e37f Mon Sep 17 00:00:00 2001 From: David Jardin Date: Mon, 21 Apr 2025 12:30:10 +0200 Subject: [PATCH 095/130] Update libraries/src/Console/AutomatedUpdatesUnregisterCommand.php Co-authored-by: Brian Teeman --- libraries/src/Console/AutomatedUpdatesUnregisterCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php b/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php index 65cad3948adf8..ba89383e6c3f6 100644 --- a/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php +++ b/libraries/src/Console/AutomatedUpdatesUnregisterCommand.php @@ -58,7 +58,7 @@ protected function configure(): void $help = "%command.name% allows to unregister a site from the automated core update service. \nUsage: php %command.full_name%"; - $this->setDescription('Unregister the current site for the unautomated core update service.'); + $this->setDescription('Unregister the current site from the unautomated core update service.'); $this->setHelp($help); } From 5ee6a4808adcc5c216eb400ba1b56b8126c15099 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Fri, 9 May 2025 16:43:53 +0200 Subject: [PATCH 096/130] cs fix --- .../com_joomlaupdate/src/Model/NotificationModel.php | 8 ++++---- .../src/Controller/NotificationController.php | 4 ++-- libraries/src/Uri/Uri.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php index b000224af2c57..284fd0cf67ffa 100644 --- a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php @@ -94,7 +94,7 @@ public function sendNotification($type, $oldVersion): void */ private function getSuperUsers($email = null): array { - $db = $this->getDatabase(); + $db = $this->getDatabase(); $emails = []; // Convert the email list to an array @@ -116,10 +116,10 @@ private function getSuperUsers($email = null): array $ret = []; try { - $rootId = (new Asset($db))->getRootId(); - $rules = Access::getAssetRules($rootId)->getData(); + $rootId = (new Asset($db))->getRootId(); + $rules = Access::getAssetRules($rootId)->getData(); $rawGroups = $rules['core.admin']->getData(); - $groups = []; + $groups = []; if (empty($rawGroups)) { return $ret; diff --git a/api/components/com_joomlaupdate/src/Controller/NotificationController.php b/api/components/com_joomlaupdate/src/Controller/NotificationController.php index 55d7de8e3b9c7..cf4a556cb1207 100644 --- a/api/components/com_joomlaupdate/src/Controller/NotificationController.php +++ b/api/components/com_joomlaupdate/src/Controller/NotificationController.php @@ -85,8 +85,8 @@ public function success() */ protected function prepareView() { - $viewType = $this->app->getDocument()->getType(); - $viewName = $this->input->get('view', $this->default_view); + $viewType = $this->app->getDocument()->getType(); + $viewName = $this->input->get('view', $this->default_view); $viewLayout = $this->input->get('layout', 'default', 'string'); try { diff --git a/libraries/src/Uri/Uri.php b/libraries/src/Uri/Uri.php index 0bcf641900c6c..a89832d9e78d4 100644 --- a/libraries/src/Uri/Uri.php +++ b/libraries/src/Uri/Uri.php @@ -148,7 +148,7 @@ public static function base($pathonly = false) } elseif (str_contains(PHP_SAPI, 'cli')) { // In CLI mode, the site base path can not be derived from the script name; the static path has to be used static::$base['prefix'] = $uri->toString(['scheme', 'host', 'port']); - static::$base['path'] = rtrim($uri->toString(['path']), '/\\'); + static::$base['path'] = rtrim($uri->toString(['path']), '/\\'); return $pathonly === false ? static::$base['prefix'] . static::$base['path'] . '/' : static::$base['path']; } else { From 78d3bc11961a65de9107b8f592ae41668c244bb8 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Fri, 9 May 2025 16:47:50 +0200 Subject: [PATCH 097/130] cs fix --- .../components/com_joomlaupdate/src/Model/NotificationModel.php | 1 - 1 file changed, 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php index 284fd0cf67ffa..a3edcc45e186a 100644 --- a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php @@ -176,5 +176,4 @@ private function getSuperUsers($email = null): array return $ret; } - } From 29c39af9d82c837d68e7d89262c0138df5176dda Mon Sep 17 00:00:00 2001 From: Harald Leithner Date: Sat, 10 May 2025 10:30:48 +0200 Subject: [PATCH 098/130] Update administrator/language/en-GB/com_joomlaupdate.ini Co-authored-by: Brian Teeman --- administrator/language/en-GB/com_joomlaupdate.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index a310fe92b2077..2079c1d00604c 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -103,10 +103,10 @@ COM_JOOMLAUPDATE_UPDATE_LOG_UNINSTALL_EXTENSIONS="Uninstalling extensions" COM_JOOMLAUPDATE_UPDATE_LOG_UPLOAD="Uploading update file" COM_JOOMLAUPDATE_UPDATE_LOG_URL="Downloading update file from %s." COM_JOOMLAUPDATE_UPDATE_LOGGING_TEST_FAIL="Logging does not work. Make sure the log folder is writable, and try again. The logging test failed with message: %s" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile of com_joomlaupdate for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! updated at {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site has been successfully automatically updated from {OLDVERSION} to {NEWVERSION}.\nPlease check your site for any unexpected behavior or malfunctions.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and the installation of such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT="Joomla! update failed for {SITENAME} – {URL}" -COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile of com_joomlaupdate for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" -COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! successfully updated at {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATING_HEAD="Update in progress" COM_JOOMLAUPDATE_UPDATING_INPROGRESS="Please wait; Joomla is being updated. This may take a while." COM_JOOMLAUPDATE_UPDATING_FAIL="The update has failed." From f15b477ac139f10d756628ffea1e21cb03c08aee Mon Sep 17 00:00:00 2001 From: Harald Leithner Date: Sat, 10 May 2025 10:30:55 +0200 Subject: [PATCH 099/130] Update api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php Co-authored-by: Brian Teeman --- .../com_joomlaupdate/src/View/Healthcheck/JsonapiView.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php index ef938b1865591..b1ad43cb70c1b 100644 --- a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php @@ -4,7 +4,7 @@ * @package Joomla.API * @subpackage com_joomlaupdate * - * @copyright (C) 2024 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ From 69dc3c6a902e40f3fd98ce630058683e5f837fa5 Mon Sep 17 00:00:00 2001 From: Harald Leithner Date: Sat, 10 May 2025 10:31:06 +0200 Subject: [PATCH 100/130] Update api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php Co-authored-by: Brian Teeman --- .../com_joomlaupdate/src/View/Notification/JsonapiView.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php index 8932719efa51c..a6d6e457251f3 100644 --- a/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php @@ -4,7 +4,7 @@ * @package Joomla.API * @subpackage com_joomlaupdate * - * @copyright (C) 2024 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ From d03134fc9f06acbf2d07133f1186e61a41bf89d0 Mon Sep 17 00:00:00 2001 From: Harald Leithner Date: Sat, 10 May 2025 10:35:51 +0200 Subject: [PATCH 101/130] Combine sql update files --- .../sql/updates/mysql/5.4.0-2025-03-16.sql | 11 -------- .../sql/updates/mysql/5.4.0-2025-03-17.sql | 3 --- .../sql/updates/mysql/5.4.0-2025-03-18.sql | 10 ------- .../sql/updates/mysql/5.4.0-2025-05-10.sql | 26 +++++++++++++++++++ .../updates/postgresql/5.4.0-2025-03-16.sql | 11 -------- .../updates/postgresql/5.4.0-2025-03-17.sql | 3 --- .../updates/postgresql/5.4.0-2025-03-18.sql | 10 ------- .../updates/postgresql/5.4.0-2025-05-10.sql | 26 +++++++++++++++++++ 8 files changed, 52 insertions(+), 48 deletions(-) delete mode 100644 administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-16.sql delete mode 100644 administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql delete mode 100644 administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-18.sql create mode 100644 administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql delete mode 100644 administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-16.sql delete mode 100644 administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql delete mode 100644 administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-18.sql create mode 100644 administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-16.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-16.sql deleted file mode 100644 index fb17b040a603e..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-16.sql +++ /dev/null @@ -1,11 +0,0 @@ -INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) -SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'autoupdate' AND e.`folder` = 'quickicon' AND e.`client_id` = 0); - -INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) -SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'joomlaupdate' AND e.`folder` = 'webservices' AND e.`client_id` = 0); - -INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subject`, `body`, `htmlbody`, `attachments`, `params`) VALUES -('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), -('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql deleted file mode 100644 index 54c1d56d149ef..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-17.sql +++ /dev/null @@ -1,3 +0,0 @@ --- add post-installation messaged for automated updates -INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) -SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-18.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-18.sql deleted file mode 100644 index 1496d0dcec732..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-03-18.sql +++ /dev/null @@ -1,10 +0,0 @@ --- disable autostart for the previous tour -UPDATE `#__guidedtours` SET `autostart` = 0 WHERE `uid` = 'joomla-whatsnew-5-3'; - -INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `published`, `language`, `note`, `access`, `uid`, `autostart`, `created`, `created_by`, `modified`, `modified_by`) VALUES -('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-4', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0); - -INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 - FROM `#__guidedtours` - WHERE `uid` = 'joomla-whatsnew-5-4'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql new file mode 100644 index 0000000000000..f3d072d99ec77 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql @@ -0,0 +1,26 @@ +INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) +SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'autoupdate' AND e.`folder` = 'quickicon' AND e.`client_id` = 0); + +INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) +SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'joomlaupdate' AND e.`folder` = 'webservices' AND e.`client_id` = 0); + +INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subject`, `body`, `htmlbody`, `attachments`, `params`) VALUES +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'); + +-- add post-installation messaged for automated updates +INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) +SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; + +-- disable autostart for the previous tour +UPDATE `#__guidedtours` SET `autostart` = 0 WHERE `uid` = 'joomla-whatsnew-5-3'; + +INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `published`, `language`, `note`, `access`, `uid`, `autostart`, `created`, `created_by`, `modified`, `modified_by`) VALUES + ('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-4', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0); + +INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 +FROM `#__guidedtours` +WHERE `uid` = 'joomla-whatsnew-5-4'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-16.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-16.sql deleted file mode 100644 index 45371501a8e58..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-16.sql +++ /dev/null @@ -1,11 +0,0 @@ -INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") -SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'autoupdate' AND e."folder" = 'quickicon' AND e."client_id" = 0); - -INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") -SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'joomlaupdate' AND e."folder" = 'webservices' AND e."client_id" = 0); - -INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subject", "body", "htmlbody", "attachments", "params") VALUES -('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), -('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql deleted file mode 100644 index 0b677991990c6..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-17.sql +++ /dev/null @@ -1,3 +0,0 @@ --- add post-installation messaged for automated updates -INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") -SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-18.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-18.sql deleted file mode 100644 index 9220b15aa3a61..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-03-18.sql +++ /dev/null @@ -1,10 +0,0 @@ --- disable autostart for the previous tour -UPDATE "#__guidedtours" SET "autostart" = 0 WHERE "uid" = 'joomla-whatsnew-5-3'; - -INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "published", "language", "note", "access", "uid", "autostart", "created", "created_by", "modified", "modified_by") VALUES -('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-4', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0); - -INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 - FROM "#__guidedtours" - WHERE "uid" = 'joomla-whatsnew-5-4'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql new file mode 100644 index 0000000000000..0c356b738d7d7 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql @@ -0,0 +1,26 @@ +INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") +SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'autoupdate' AND e."folder" = 'quickicon' AND e."client_id" = 0); + +INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") +SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'joomlaupdate' AND e."folder" = 'webservices' AND e."client_id" = 0); + +INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subject", "body", "htmlbody", "attachments", "params") VALUES +('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), +('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'); + +-- add post-installation messaged for automated updates +INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") +SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; + +-- disable autostart for the previous tour +UPDATE "#__guidedtours" SET "autostart" = 0 WHERE "uid" = 'joomla-whatsnew-5-3'; + +INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "published", "language", "note", "access", "uid", "autostart", "created", "created_by", "modified", "modified_by") VALUES + ('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-4', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0); + +INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 +FROM "#__guidedtours" +WHERE "uid" = 'joomla-whatsnew-5-4'; From d4925d8022dad5738c741f79038679e0058f7fa5 Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Sat, 10 May 2025 11:12:13 +0200 Subject: [PATCH 102/130] Fix ordering of webservices plugins --- installation/sql/mysql/base.sql | 24 ++++++++++++------------ installation/sql/postgresql/base.sql | 26 +++++++++++++------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index fdc305d4c2307..21db8b7c0eced 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -393,18 +393,18 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'plg_webservices_content', 'plugin', 'content', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), (0, 'plg_webservices_installer', 'plugin', 'installer', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), (0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), -(0, 'plg_webservices_languages', 'plugin', 'languages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), -(0, 'plg_webservices_media', 'plugin', 'media', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), -(0, 'plg_webservices_menus', 'plugin', 'menus', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), -(0, 'plg_webservices_messages', 'plugin', 'messages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 8, 0), -(0, 'plg_webservices_modules', 'plugin', 'modules', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 9, 0), -(0, 'plg_webservices_newsfeeds', 'plugin', 'newsfeeds', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 10, 0), -(0, 'plg_webservices_plugins', 'plugin', 'plugins', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 11, 0), -(0, 'plg_webservices_privacy', 'plugin', 'privacy', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 12, 0), -(0, 'plg_webservices_redirect', 'plugin', 'redirect', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 13, 0), -(0, 'plg_webservices_tags', 'plugin', 'tags', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 14, 0), -(0, 'plg_webservices_templates', 'plugin', 'templates', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 15, 0), -(0, 'plg_webservices_users', 'plugin', 'users', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 16, 0), +(0, 'plg_webservices_languages', 'plugin', 'languages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), +(0, 'plg_webservices_media', 'plugin', 'media', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 8, 0), +(0, 'plg_webservices_menus', 'plugin', 'menus', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 9, 0), +(0, 'plg_webservices_messages', 'plugin', 'messages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 10, 0), +(0, 'plg_webservices_modules', 'plugin', 'modules', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 11, 0), +(0, 'plg_webservices_newsfeeds', 'plugin', 'newsfeeds', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 12, 0), +(0, 'plg_webservices_plugins', 'plugin', 'plugins', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 13, 0), +(0, 'plg_webservices_privacy', 'plugin', 'privacy', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 14, 0), +(0, 'plg_webservices_redirect', 'plugin', 'redirect', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 15, 0), +(0, 'plg_webservices_tags', 'plugin', 'tags', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 16, 0), +(0, 'plg_webservices_templates', 'plugin', 'templates', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 17, 0), +(0, 'plg_webservices_users', 'plugin', 'users', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 18, 0), (0, 'plg_workflow_featuring', 'plugin', 'featuring', 'workflow', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_workflow_notification', 'plugin', 'notification', 'workflow', 0, 1, 1, 0, 1, '', '{}', '', 2, 0), (0, 'plg_workflow_publishing', 'plugin', 'publishing', 'workflow', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index 0ec28474258de..5a32d842a845a 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -398,19 +398,19 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'plg_webservices_contact', 'plugin', 'contact', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), (0, 'plg_webservices_content', 'plugin', 'content', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), (0, 'plg_webservices_installer', 'plugin', 'installer', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), -(0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), -(0, 'plg_webservices_languages', 'plugin', 'languages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), -(0, 'plg_webservices_media', 'plugin', 'media', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), -(0, 'plg_webservices_menus', 'plugin', 'menus', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), -(0, 'plg_webservices_messages', 'plugin', 'messages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 8, 0), -(0, 'plg_webservices_modules', 'plugin', 'modules', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 9, 0), -(0, 'plg_webservices_newsfeeds', 'plugin', 'newsfeeds', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 10, 0), -(0, 'plg_webservices_plugins', 'plugin', 'plugins', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 11, 0), -(0, 'plg_webservices_privacy', 'plugin', 'privacy', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 12, 0), -(0, 'plg_webservices_redirect', 'plugin', 'redirect', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 13, 0), -(0, 'plg_webservices_tags', 'plugin', 'tags', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 14, 0), -(0, 'plg_webservices_templates', 'plugin', 'templates', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 15, 0), -(0, 'plg_webservices_users', 'plugin', 'users', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 16, 0), +(0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), +(0, 'plg_webservices_languages', 'plugin', 'languages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), +(0, 'plg_webservices_media', 'plugin', 'media', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 8, 0), +(0, 'plg_webservices_menus', 'plugin', 'menus', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 9, 0), +(0, 'plg_webservices_messages', 'plugin', 'messages', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 10, 0), +(0, 'plg_webservices_modules', 'plugin', 'modules', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 11, 0), +(0, 'plg_webservices_newsfeeds', 'plugin', 'newsfeeds', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 12, 0), +(0, 'plg_webservices_plugins', 'plugin', 'plugins', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 13, 0), +(0, 'plg_webservices_privacy', 'plugin', 'privacy', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 14, 0), +(0, 'plg_webservices_redirect', 'plugin', 'redirect', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 15, 0), +(0, 'plg_webservices_tags', 'plugin', 'tags', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 16, 0), +(0, 'plg_webservices_templates', 'plugin', 'templates', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 17, 0), +(0, 'plg_webservices_users', 'plugin', 'users', 'webservices', 0, 1, 1, 0, 1, '', '{}', '', 18, 0), (0, 'plg_workflow_featuring', 'plugin', 'featuring', 'workflow', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_workflow_notification', 'plugin', 'notification', 'workflow', 0, 1, 1, 0, 1, '', '{}', '', 2, 0), (0, 'plg_workflow_publishing', 'plugin', 'publishing', 'workflow', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), From 7a9c27c8a989defd28d66f1460a9d846ee68e888 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 10 May 2025 17:16:18 +0200 Subject: [PATCH 103/130] adjust string sorting --- administrator/language/en-GB/plg_actionlog_joomla.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/administrator/language/en-GB/plg_actionlog_joomla.ini b/administrator/language/en-GB/plg_actionlog_joomla.ini index 05415c26d6594..dc2d74017868f 100644 --- a/administrator/language/en-GB/plg_actionlog_joomla.ini +++ b/administrator/language/en-GB/plg_actionlog_joomla.ini @@ -40,6 +40,7 @@ PLG_ACTIONLOG_JOOMLA_TYPE_TEMPLATE="template" PLG_ACTIONLOG_JOOMLA_TYPE_USER="user" PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP="user group" PLG_ACTIONLOG_JOOMLA_TYPE_USER_NOTE="user note" +; User actions PLG_ACTIONLOG_JOOMLA_USER_BLOCK="User {username} blocked user {title}" PLG_ACTIONLOG_JOOMLA_USER_CACHE="User {username} deleted cache group {group}" PLG_ACTIONLOG_JOOMLA_USER_CHECKIN="User {username} performed a check in to table {table}" @@ -55,8 +56,9 @@ PLG_ACTIONLOG_JOOMLA_USER_RESET_COMPLETE="User {username PLG_ACTIONLOG_JOOMLA_USER_RESET_REQUEST="User {username} requested a password reset for their account" PLG_ACTIONLOG_JOOMLA_USER_UNBLOCK="User {username} unblocked user {title}" PLG_ACTIONLOG_JOOMLA_USER_UPDATE="User {username} updated Joomla from {oldversion} to {version}" +; Automatic updates PLG_ACTIONLOG_JOOMLA_SYSTEM_UPDATE="An automated process updated Joomla from {oldversion} to {version}" -; Component +; Config PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED="User {username} changed settings of the application configuration" PLG_ACTIONLOG_JOOMLA_COMPONENT_CONFIG_UPDATED="User {username} changed settings of the component {extension_name}" ; Extensions From 55b346480466ebc93becfa44d5e303f6a609de44 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 10 May 2025 17:16:57 +0200 Subject: [PATCH 104/130] Apply suggestions from code review Co-authored-by: Richard Fath Co-authored-by: Brian Teeman --- .../com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql | 2 +- .../com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql | 2 +- .../com_joomlaupdate/src/Model/NotificationModel.php | 2 +- administrator/language/en-GB/com_joomlaupdate.ini | 7 ++++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql index f3d072d99ec77..e3d6994d83b18 100644 --- a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql +++ b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql @@ -10,7 +10,7 @@ INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subjec ('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), ('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'); --- add post-installation messaged for automated updates +-- add post-installation message for automated updates INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql index 0c356b738d7d7..847a14d4cc398 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql @@ -10,7 +10,7 @@ INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subjec ('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), ('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'); --- add post-installation messaged for automated updates +-- add post-installation message for automated updates INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; diff --git a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php index a3edcc45e186a..b065e40855031 100644 --- a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php @@ -4,7 +4,7 @@ * @package Joomla.Administrator * @subpackage com_joomlaupdate * - * @copyright (C) 2012 Open Source Matters, Inc. + * @copyright (C) 2025 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 2079c1d00604c..ec3c9b59447d1 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -3,10 +3,10 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS="Registered to autoupdate service" COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR="Error while registering to autoupdate service: %s (%d)" -COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Unregistered from autoupdate service" +COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS="Registered to autoupdate service" COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from autoupdate service: %s (%d)" +COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Unregistered from autoupdate service" COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_DISABLED_LABEL=" Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." @@ -21,8 +21,9 @@ COM_JOOMLAUPDATE_CONFIG_CUSTOMURL_LABEL="Custom URL" COM_JOOMLAUPDATE_CONFIG_SOURCES_DESC="Configure where Joomla gets its update information from." COM_JOOMLAUPDATE_CONFIG_SOURCES_LABEL="Update Source" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM="Custom URL" -COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_LABEL="Last Checked" COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_DESC="The last time the automated updates server could reach this site. If this date is too old, something is wrong with the automated updates and you should re-initiate the process by re-saving the configuration." +COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_LABEL="Last Checked" + COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM_ERROR="The custom URL field is empty." COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_DEFAULT="Default" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_LABEL="Update Channel" From 7646135698de030f15aad6d32fe94ce2b7743dea Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sat, 10 May 2025 17:27:54 +0200 Subject: [PATCH 105/130] fix missing import --- api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php | 1 + 1 file changed, 1 insertion(+) diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index e5f66ebe4b1eb..3a11693c20061 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -11,6 +11,7 @@ namespace Joomla\Component\Joomlaupdate\Api\View\Updates; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Uri\Uri; From 6451720ddf1be8dc678d56f3a12c0b1ad343b3df Mon Sep 17 00:00:00 2001 From: David Jardin Date: Tue, 13 May 2025 08:58:01 +0200 Subject: [PATCH 106/130] update i18n strings --- administrator/language/en-GB/com_joomlaupdate.ini | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 045cb5da0e72d..7d03f5263148e 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -3,10 +3,10 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR="Error while registering to autoupdate service: %s (%d)" -COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS="Registered to autoupdate service" -COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from autoupdate service: %s (%d)" -COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Unregistered from autoupdate service" +COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR="Error while registering to autoupdate service: %s (%d)." +COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS="Registered to autoupdate service." +COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from autoupdate service: %s (%d)." +COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Unregistered from autoupdate service." COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_DISABLED_LABEL=" Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." @@ -28,7 +28,7 @@ COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM_ERROR="The custom URL field is empty COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_DEFAULT="Default" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_LABEL="Update Channel" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_NEXT="Joomla Next" -COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_DESC="This is the update token that this site uses to authenticate with the Joomla Update Server. It is used to ensure that only your site can update itself." +COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_DESC="This is the update token that this site uses to authenticate with the Joomla Automated Updates server. It is used to ensure that only your site can update itself." COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_LABEL="Update Token" ; Deprecated, will be removed with 6.0 COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_TESTING="Testing" @@ -67,7 +67,7 @@ COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_REASON_PHP="Your PHP version \"%1$s\" is COM_JOOMLAUPDATE_NODOWNLOAD_EMPTYSTATE_TITLE="This site can't be updated to Joomla %1$s" COM_JOOMLAUPDATE_OVERVIEW="Joomla Update" COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION="Activate Automated Updates" -COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION="Joomla 5.4 now supports Automated updates for better security and performance. Select \"Activate Automated Updates\" to stay up to date effortlessly!" +COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION="With Automated Updates you can keep your Joomla site secure and up-to-date—automatically, reliably, effortlessly. Activate Automated Updates now by clicking on the \"Activate Automated Updates\" button." COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE="Automated Joomla Updates" COM_JOOMLAUPDATE_PREUPDATE_CHECK_CAPTION="Server settings to check before update." COM_JOOMLAUPDATE_PREUPDATE_CHECK_COMPLETED_YOU_HAVE_DANGEROUS_PLUGINS="There are plugins installed and enabled that could interfere with the Joomla update and result in a failed update that leaves the site inaccessible.

You are strongly advised to update, disable or uninstall these plugins before upgrading." From fe3e930577374be9c3c0ee1c481f8d1b35492a57 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Tue, 13 May 2025 10:30:14 +0200 Subject: [PATCH 107/130] fix notification subjects --- administrator/language/en-GB/com_joomlaupdate.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 7d03f5263148e..2f056cc0915b0 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -105,9 +105,9 @@ COM_JOOMLAUPDATE_UPDATE_LOG_UPLOAD="Uploading update file" COM_JOOMLAUPDATE_UPDATE_LOG_URL="Downloading update file from %s." COM_JOOMLAUPDATE_UPDATE_LOGGING_TEST_FAIL="Logging does not work. Make sure the log folder is writable, and try again. The logging test failed with message: %s" COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile of com_joomlaupdate for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" -COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! updated at {SITENAME} – {URL}" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! update failed {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site has been successfully automatically updated from {OLDVERSION} to {NEWVERSION}.\nPlease check your site for any unexpected behavior or malfunctions.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and the installation of such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" -COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT="Joomla! update failed for {SITENAME} – {URL}" +COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT="Joomla! updated successfully at {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATING_HEAD="Update in progress" COM_JOOMLAUPDATE_UPDATING_INPROGRESS="Please wait; Joomla is being updated. This may take a while." COM_JOOMLAUPDATE_UPDATING_FAIL="The update has failed." From 91499d66d8c20c0d6c77a7a12b9bf7fc65eab246 Mon Sep 17 00:00:00 2001 From: Brian Teeman Date: Tue, 13 May 2025 09:53:33 +0100 Subject: [PATCH 108/130] Quickicon Link This small PR ensures that the link on the quickicon goes directly to the automated updates tab of the joomla update component options --- plugins/quickicon/autoupdate/src/Extension/Autoupdate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/quickicon/autoupdate/src/Extension/Autoupdate.php b/plugins/quickicon/autoupdate/src/Extension/Autoupdate.php index 573a594e51a8e..a33bff7e3940c 100644 --- a/plugins/quickicon/autoupdate/src/Extension/Autoupdate.php +++ b/plugins/quickicon/autoupdate/src/Extension/Autoupdate.php @@ -127,7 +127,7 @@ public function getAutoUpdateStatusNotification(QuickIconsEvent $event) $result[] = [ [ - 'link' => 'index.php?option=com_config&view=component&component=com_joomlaupdate', + 'link' => 'index.php?option=com_config&view=component&component=com_joomlaupdate#automated-updates', 'image' => 'icon-health', 'icon' => '', 'text' => Text::_('PLG_QUICKICON_AUTOUPDATE_CHECKING'), From 58c39e6fa283576408edc2eb3622aa04131d2906 Mon Sep 17 00:00:00 2001 From: Brian Teeman Date: Tue, 13 May 2025 10:14:52 +0100 Subject: [PATCH 109/130] Update plg_quickicon_autoupdate.ini I understand why the string "working" was chosen but I think it is better to simply say "enabled" we know it is working as there are multiple different messages to show there is a problem (Unknown, disabled and outdated) IT would be more consistent with the rest of Joomla to say enabled AND someone might think that working = joomla update in progress --- administrator/language/en-GB/plg_quickicon_autoupdate.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/administrator/language/en-GB/plg_quickicon_autoupdate.ini b/administrator/language/en-GB/plg_quickicon_autoupdate.ini index bb42d09d464f8..16470178372ca 100644 --- a/administrator/language/en-GB/plg_quickicon_autoupdate.ini +++ b/administrator/language/en-GB/plg_quickicon_autoupdate.ini @@ -9,7 +9,6 @@ PLG_QUICKICON_AUTOUPDATE_DISABLED="Automated Updates are disabled." PLG_QUICKICON_AUTOUPDATE_ERROR="Unknown Health status …" PLG_QUICKICON_AUTOUPDATE_GROUP_DESC="The group of this plugin (this value is compared with the group value used in Quick Icons modules to inject icons)." PLG_QUICKICON_AUTOUPDATE_GROUP_LABEL="Group" -PLG_QUICKICON_AUTOUPDATE_OK="Automated Updates working." +PLG_QUICKICON_AUTOUPDATE_OK="Automated Updates are enabled." PLG_QUICKICON_AUTOUPDATE_OUTDATED="Automated Updates connection broken." PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of automated updates and notifies you when you visit the Home Dashboard page." - From 03aa9fd6c4ee0e3ef636883545fb4d63b4827598 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Tue, 13 May 2025 11:47:46 +0200 Subject: [PATCH 110/130] Added mail template i18n strings --- administrator/language/en-GB/com_joomlaupdate.ini | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 2f056cc0915b0..65a5af9c7c16d 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -93,6 +93,8 @@ COM_JOOMLAUPDATE_UPDATE_CHECK="Update Check" COM_JOOMLAUPDATE_UPDATE_CONFIRM_BACKUP="I'm aware that a backup before any update is highly recommended." COM_JOOMLAUPDATE_UPDATE_EMPTYSTATE_TITLE="Update your site to \"Joomla! %s\"" COM_JOOMLAUPDATE_UPDATE_EMPTYSTATE_BUTTON_ADD="Start update" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile of com_joomlaupdate for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! update failed {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATE_LOG_CLEANUP="Cleaning up after installation." COM_JOOMLAUPDATE_UPDATE_LOG_COMPLETE="Update to version %s is complete." COM_JOOMLAUPDATE_UPDATE_LOG_DELETE_FILES="Deleting removed files and folders." @@ -103,9 +105,11 @@ COM_JOOMLAUPDATE_UPDATE_LOG_START="Update started by user %2$s (%1$s). Old versi COM_JOOMLAUPDATE_UPDATE_LOG_UNINSTALL_EXTENSIONS="Uninstalling extensions" COM_JOOMLAUPDATE_UPDATE_LOG_UPLOAD="Uploading update file" COM_JOOMLAUPDATE_UPDATE_LOG_URL="Downloading update file from %s." +COM_JOOMLAUPDATE_MAIL_UPDATE_FAILED_DESC="Send to the site administrators if an Automated Joomla Update failed." +COM_JOOMLAUPDATE_MAIL_UPDATE_FAILED_TITLE="Automated Joomla Update failed" +COM_JOOMLAUPDATE_MAIL_UPDATE_SUCCESS_DESC="Send to the site administrators if an Automated Joomla Update succeeded." +COM_JOOMLAUPDATE_MAIL_UPDATE_SUCCESS_TITLE="Automated Joomla Update succeeded" COM_JOOMLAUPDATE_UPDATE_LOGGING_TEST_FAIL="Logging does not work. Make sure the log folder is writable, and try again. The logging test failed with message: %s" -COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile of com_joomlaupdate for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" -COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! update failed {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site has been successfully automatically updated from {OLDVERSION} to {NEWVERSION}.\nPlease check your site for any unexpected behavior or malfunctions.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and the installation of such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT="Joomla! updated successfully at {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATING_HEAD="Update in progress" From c32ae03b01c82ebc481d0ef82e7f2ab73ed04af6 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Tue, 13 May 2025 12:14:17 +0200 Subject: [PATCH 111/130] Update administrator/language/en-GB/com_joomlaupdate.ini Co-authored-by: Brian Teeman --- administrator/language/en-GB/com_joomlaupdate.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 65a5af9c7c16d..ad0be9c547772 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -106,7 +106,7 @@ COM_JOOMLAUPDATE_UPDATE_LOG_UNINSTALL_EXTENSIONS="Uninstalling extensions" COM_JOOMLAUPDATE_UPDATE_LOG_UPLOAD="Uploading update file" COM_JOOMLAUPDATE_UPDATE_LOG_URL="Downloading update file from %s." COM_JOOMLAUPDATE_MAIL_UPDATE_FAILED_DESC="Send to the site administrators if an Automated Joomla Update failed." -COM_JOOMLAUPDATE_MAIL_UPDATE_FAILED_TITLE="Automated Joomla Update failed" +COM_JOOMLAUPDATE_MAIL_UPDATE_FAILED_TITLE="Automated Joomla Update Failed" COM_JOOMLAUPDATE_MAIL_UPDATE_SUCCESS_DESC="Send to the site administrators if an Automated Joomla Update succeeded." COM_JOOMLAUPDATE_MAIL_UPDATE_SUCCESS_TITLE="Automated Joomla Update succeeded" COM_JOOMLAUPDATE_UPDATE_LOGGING_TEST_FAIL="Logging does not work. Make sure the log folder is writable, and try again. The logging test failed with message: %s" From ec9a66ef90b6a15643ba608ce246e7831fcbe9a5 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Tue, 13 May 2025 12:14:38 +0200 Subject: [PATCH 112/130] Apply suggestions from code review Co-authored-by: Brian Teeman --- administrator/language/en-GB/com_joomlaupdate.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index ad0be9c547772..0e0c35968761e 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -93,7 +93,7 @@ COM_JOOMLAUPDATE_UPDATE_CHECK="Update Check" COM_JOOMLAUPDATE_UPDATE_CONFIRM_BACKUP="I'm aware that a backup before any update is highly recommended." COM_JOOMLAUPDATE_UPDATE_EMPTYSTATE_TITLE="Update your site to \"Joomla! %s\"" COM_JOOMLAUPDATE_UPDATE_EMPTYSTATE_BUTTON_ADD="Start update" -COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile of com_joomlaupdate for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile '/administrator/logs/joomla_update.php' for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! update failed {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATE_LOG_CLEANUP="Cleaning up after installation." COM_JOOMLAUPDATE_UPDATE_LOG_COMPLETE="Update to version %s is complete." @@ -108,7 +108,7 @@ COM_JOOMLAUPDATE_UPDATE_LOG_URL="Downloading update file from %s." COM_JOOMLAUPDATE_MAIL_UPDATE_FAILED_DESC="Send to the site administrators if an Automated Joomla Update failed." COM_JOOMLAUPDATE_MAIL_UPDATE_FAILED_TITLE="Automated Joomla Update Failed" COM_JOOMLAUPDATE_MAIL_UPDATE_SUCCESS_DESC="Send to the site administrators if an Automated Joomla Update succeeded." -COM_JOOMLAUPDATE_MAIL_UPDATE_SUCCESS_TITLE="Automated Joomla Update succeeded" +COM_JOOMLAUPDATE_MAIL_UPDATE_SUCCESS_TITLE="Automated Joomla Update Succeeded" COM_JOOMLAUPDATE_UPDATE_LOGGING_TEST_FAIL="Logging does not work. Make sure the log folder is writable, and try again. The logging test failed with message: %s" COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site has been successfully automatically updated from {OLDVERSION} to {NEWVERSION}.\nPlease check your site for any unexpected behavior or malfunctions.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and the installation of such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT="Joomla! updated successfully at {SITENAME} – {URL}" From 458a762b96a2cdfbef6cfbb446d701a9e461ee3a Mon Sep 17 00:00:00 2001 From: David Jardin Date: Wed, 14 May 2025 08:58:05 +0200 Subject: [PATCH 113/130] Apply suggestions from code review Co-authored-by: Tobias Zulauf --- .../com_joomlaupdate/postinstall/autoupdate.php | 1 + .../com_joomlaupdate/src/Model/NotificationModel.php | 10 ++++++++++ .../com_joomlaupdate/src/View/Updates/JsonapiView.php | 9 +++++++++ .../joomlaupdate/src/Extension/Joomlaupdate.php | 4 ++-- plugins/quickicon/autoupdate/services/provider.php | 3 ++- .../joomlaupdate/src/Extension/Joomlaupdate.php | 5 ++--- 6 files changed, 26 insertions(+), 6 deletions(-) diff --git a/administrator/components/com_joomlaupdate/postinstall/autoupdate.php b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php index 9324309d9a8a9..f44aa08ef9061 100644 --- a/administrator/components/com_joomlaupdate/postinstall/autoupdate.php +++ b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php @@ -44,6 +44,7 @@ function com_joomlaupdate_postinstall_autoupdate_condition(): bool function com_joomlaupdate_postinstall_autoupdate_action(): void { $db = Factory::getContainer()->get(DatabaseInterface::class); + // Get extension row $extension = new Extension($db); $extensionId = $extension->find(['element' => 'com_joomlaupdate']); diff --git a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php index b065e40855031..900397082e16b 100644 --- a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php @@ -34,6 +34,16 @@ */ final class NotificationModel extends BaseDatabaseModel { + /** + * Sends the update notification to the specificly configured emails and superusers + * + * @param string $type The type of notification to send. This is the last key for the mail template + * @param string $oldVersion The old version from before the update + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ public function sendNotification($type, $oldVersion): void { $params = ComponentHelper::getParams('com_joomlaupdate'); diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index 3a11693c20061..10286beef1344 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -89,6 +89,15 @@ public function prepareUpdate(string $targetVersion): string return $this->getDocument()->render(); } + /** + * Run the finalize update steps + * + * @param string $fromVersion The from version + * + * @return string The rendered data + * + * @since __DEPLOY_VERSION__ + */ public function finalizeUpdate($fromVersion) { /** diff --git a/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php index 6fd22c69f394d..52dd35254e1a6 100644 --- a/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/extension/joomlaupdate/src/Extension/Joomlaupdate.php @@ -77,8 +77,8 @@ public function onExtensionBeforeSave(\Joomla\CMS\Event\Model\BeforeSaveEvent $e $data = new Registry($table->params); - $autoupdateStatus = (int)$data->get('autoupdate'); - $autoupdateRegisterStatus = (int)$data->get('autoupdate_status'); + $autoupdateStatus = (int) $data->get('autoupdate'); + $autoupdateRegisterStatus = (int) $data->get('autoupdate_status'); if ($data->get('updatesource') !== 'default' || $data->get('minimum_stability') !== '4') { // If we are not using Joomla Update Server or not using Stable Version disable the autoupdate diff --git a/plugins/quickicon/autoupdate/services/provider.php b/plugins/quickicon/autoupdate/services/provider.php index 22860f95a0753..cd62d4858ece2 100644 --- a/plugins/quickicon/autoupdate/services/provider.php +++ b/plugins/quickicon/autoupdate/services/provider.php @@ -17,7 +17,8 @@ use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Quickicon\Autoupdate\Extension\Autoupdate; -return new class () implements ServiceProviderInterface { +return new class () implements ServiceProviderInterface +{ /** * Registers the service provider with a DI container. * diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index 313da605ffc54..b2a6b3820b661 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -51,9 +51,8 @@ public static function getSubscribedEvents(): array */ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void { - $router = $event->getRouter(); - - $defaults = ['component' => 'com_joomlaupdate', 'public' => true]; + $router = $event->getRouter(); + $defaults = ['component' => 'com_joomlaupdate', 'public' => true]; $routes = [ new Route(['GET'], 'v1/joomlaupdate/healthcheck', 'healthcheck.show', [], $defaults), From 8d50a2c5da2c1d5e22b4bb8a55bf86d335ea4f36 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Wed, 14 May 2025 09:00:28 +0200 Subject: [PATCH 114/130] Fix docblock --- .../com_joomlaupdate/src/View/Notification/JsonapiView.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php index a6d6e457251f3..29120d3ce4575 100644 --- a/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Notification/JsonapiView.php @@ -27,7 +27,7 @@ class JsonapiView extends BaseApiView { /** - * Generates the health check output + * Sends the update result notification * * @return string The rendered data * From 75ed12bc10a58042ab090814242c0bed1b428092 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Wed, 14 May 2025 16:40:44 +0200 Subject: [PATCH 115/130] fix site url --- .../com_joomlaupdate/src/Model/NotificationModel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php index 900397082e16b..edb3b75673a8a 100644 --- a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php @@ -35,7 +35,7 @@ final class NotificationModel extends BaseDatabaseModel { /** - * Sends the update notification to the specificly configured emails and superusers + * Sends the update notification to the specificly configured emails and superusers * * @param string $type The type of notification to send. This is the last key for the mail template * @param string $oldVersion The old version from before the update @@ -75,7 +75,7 @@ public function sendNotification($type, $oldVersion): void 'oldversion' => $oldVersion, 'newversion' => $newVersion, 'sitename' => $sitename, - 'url' => Uri::base(), + 'url' => Uri::root(), ]; // Send the emails to the Super Users From d449d0c422a56d1b99d3bb9920137e41a805bf0f Mon Sep 17 00:00:00 2001 From: Richard Fath Date: Wed, 14 May 2025 16:52:29 +0200 Subject: [PATCH 116/130] Fix PHPCS --- .../com_joomlaupdate/src/View/Updates/JsonapiView.php | 2 +- plugins/quickicon/autoupdate/services/provider.php | 3 +-- .../webservices/joomlaupdate/src/Extension/Joomlaupdate.php | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index 10286beef1344..1857e64c4ba0a 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -90,7 +90,7 @@ public function prepareUpdate(string $targetVersion): string } /** - * Run the finalize update steps + * Run the finalize update steps * * @param string $fromVersion The from version * diff --git a/plugins/quickicon/autoupdate/services/provider.php b/plugins/quickicon/autoupdate/services/provider.php index cd62d4858ece2..22860f95a0753 100644 --- a/plugins/quickicon/autoupdate/services/provider.php +++ b/plugins/quickicon/autoupdate/services/provider.php @@ -17,8 +17,7 @@ use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Quickicon\Autoupdate\Extension\Autoupdate; -return new class () implements ServiceProviderInterface -{ +return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * diff --git a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php index b2a6b3820b661..a526f56e2fa83 100644 --- a/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php +++ b/plugins/webservices/joomlaupdate/src/Extension/Joomlaupdate.php @@ -51,7 +51,7 @@ public static function getSubscribedEvents(): array */ public function onBeforeApiRoute(BeforeApiRouteEvent $event): void { - $router = $event->getRouter(); + $router = $event->getRouter(); $defaults = ['component' => 'com_joomlaupdate', 'public' => true]; $routes = [ From bce0f6d55303fd64dbcf63ec64adc2839b038eaa Mon Sep 17 00:00:00 2001 From: Brian Teeman Date: Wed, 14 May 2025 17:39:17 +0100 Subject: [PATCH 117/130] automated_updates_email All the fields except for the admin email are hidden when the update source is not default and level is stable. I am assuming it is an oversight that the admin email field was not hidden --- administrator/components/com_joomlaupdate/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index e74251b5165ea..ddfbcdd162a4b 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -123,7 +123,7 @@ type="text" label="COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_UPDATE_EMAIL_LABEL" description="COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_UPDATE_EMAIL_DESCRIPTION" - showon="autoupdate:1" + showon="updatesource:default[AND]minimum_stability:4[AND]autoupdate:1" /> From fd7f9136eb97130101edbc01442a085052c8b866 Mon Sep 17 00:00:00 2001 From: Brian Teeman Date: Wed, 14 May 2025 17:44:28 +0100 Subject: [PATCH 118/130] Update com_joomlaupdate.ini space should not be used in a language string for padding. And its not needed anyway as the icon already has me-2 class which is sufficient --- administrator/language/en-GB/com_joomlaupdate.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 0e0c35968761e..fad23cec60bee 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -9,7 +9,7 @@ COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from aut COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Unregistered from autoupdate service." COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." -COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_DISABLED_LABEL=" Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." +COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_DISABLED_LABEL="Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_LABEL="Automated Updates" COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_DESC="Automatically update Joomla to the latest version when it is available." COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_LABEL="Automated Update" From 3c732b3eb06ab240a473993c04318d627780b5c4 Mon Sep 17 00:00:00 2001 From: Brian Teeman Date: Thu, 15 May 2025 08:30:33 +0100 Subject: [PATCH 119/130] Update com_joomlaupdate.ini changed autoupdate to automated update for consistency --- administrator/language/en-GB/com_joomlaupdate.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index fad23cec60bee..c1b1c5b4b6a18 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -3,10 +3,10 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR="Error while registering to autoupdate service: %s (%d)." -COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS="Registered to autoupdate service." -COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from autoupdate service: %s (%d)." -COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Unregistered from autoupdate service." +COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR="Error while registering to automated update service: %s (%d)." +COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_SUCCESS="Registered to automated update service." +COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_ERROR="Error while unregistering from automated update service: %s (%d)." +COM_JOOMLAUPDATE_AUTOUPDATE_UNREGISTER_SUCCESS="Unregistered from automated update service." COM_JOOMLAUPDATE_CAPTIVE_HEADLINE="Confirm your credentials" COM_JOOMLAUPDATE_CHECKED_UPDATES="Checked for updates." COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_DISABLED_LABEL="Automated updates are only supported for the \"default\" channel and \"Minimum Stability\" \"Stable\"." From ddff7f1dae68c1f805e1c62e3b4a09eeea253096 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 15 May 2025 10:32:10 +0200 Subject: [PATCH 120/130] Check stability and channel in quickicon status output --- .../com_joomlaupdate/src/Controller/UpdateController.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 1dd3405032639..9efa40abf06f8 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -18,6 +18,7 @@ use Joomla\CMS\MVC\Controller\BaseController; use Joomla\CMS\Response\JsonResponse; use Joomla\CMS\Session\Session; +use Joomla\CMS\Updater\Updater; use Joomla\Component\Joomlaupdate\Administrator\Enum\AutoupdateRegisterState; use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; @@ -754,11 +755,14 @@ public function healthstatus() $this->app->close(); } - // Default case: connection already active, check date + // Default case: connection already configured, check update source and date $lastCheck = date_create_from_format('Y-m-d H:i:s', $params->get('update_last_check', '')); $result = [ - 'active' => (int) $params->get('autoupdate'), + 'active' => ((int) $params->get('autoupdate') + && $params->get('updatesource', 'default') === 'default' + && (int) $params->get('minimum_stability', Updater::STABILITY_STABLE) === Updater::STABILITY_STABLE + ), 'healthy' => $lastCheck !== false && $lastCheck->diff(new \DateTime())->days < 4, ]; From 557e7eb585f6ab5e757049ae4660ad246f0644fb Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 15 May 2025 10:37:16 +0200 Subject: [PATCH 121/130] respect user time in last_check-Date --- administrator/components/com_joomlaupdate/config.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index ddfbcdd162a4b..2d8fef06e2b87 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -105,7 +105,9 @@ /> Date: Thu, 15 May 2025 11:49:05 +0100 Subject: [PATCH 122/130] Update NotificationModel.php Spelling and spaces --- .../com_joomlaupdate/src/Model/NotificationModel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php index edb3b75673a8a..aa9371b49d0c2 100644 --- a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php @@ -35,9 +35,9 @@ final class NotificationModel extends BaseDatabaseModel { /** - * Sends the update notification to the specificly configured emails and superusers + * Sends the update notification to the specifically configured emails and superusers * - * @param string $type The type of notification to send. This is the last key for the mail template + * @param string $type The type of notification to send. This is the last key for the mail template * @param string $oldVersion The old version from before the update * * @return void From b148bd9c9e575e9eadfdafd11ddf88d299ddc3c9 Mon Sep 17 00:00:00 2001 From: Brian Teeman Date: Thu, 15 May 2025 12:27:16 +0100 Subject: [PATCH 123/130] Update guidedtours.joomla_whatsnew_5_4.ini Remove redundant title text on the button - it already has perfectly accessible discernible text Remove target = _blank - this obviously was an oversight as it sucks for accessibility and should not be used --- .../language/en-GB/guidedtours.joomla_whatsnew_5_4.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini index 177c1cf370b3e..cb87677f6fd6f 100644 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini @@ -3,5 +3,5 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION="

Welcome to Joomla 5.4!

\"Display

Automated Updates are here!

Joomla! 5.4 now supports automated updates for better security and performance.

Enable your automated updates now

Stay safe and secure!

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION="

Welcome to Joomla 5.4!

\"Display

Automated Updates are here!

Joomla! 5.4 now supports automated updates for better security and performance.

Enable your automated updates now

Stay safe and secure!

" COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE="What’s New in Joomla 5.4!" From 6ff518739c0519489eba5be60b9596cb6c7040f6 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 15 May 2025 14:32:52 +0200 Subject: [PATCH 124/130] cs fix --- .../com_joomlaupdate/src/Controller/UpdateController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 9efa40abf06f8..26ed086123250 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -759,7 +759,8 @@ public function healthstatus() $lastCheck = date_create_from_format('Y-m-d H:i:s', $params->get('update_last_check', '')); $result = [ - 'active' => ((int) $params->get('autoupdate') + 'active' => ( + (int) $params->get('autoupdate') && $params->get('updatesource', 'default') === 'default' && (int) $params->get('minimum_stability', Updater::STABILITY_STABLE) === Updater::STABILITY_STABLE ), From a339bc2a16a470e4ce44b92038ef6336788207fe Mon Sep 17 00:00:00 2001 From: David Jardin Date: Thu, 15 May 2025 14:35:44 +0200 Subject: [PATCH 125/130] cs fix --- .../com_joomlaupdate/src/Controller/UpdateController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 26ed086123250..3fc8e3895d432 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -759,7 +759,7 @@ public function healthstatus() $lastCheck = date_create_from_format('Y-m-d H:i:s', $params->get('update_last_check', '')); $result = [ - 'active' => ( + 'active' => ( (int) $params->get('autoupdate') && $params->get('updatesource', 'default') === 'default' && (int) $params->get('minimum_stability', Updater::STABILITY_STABLE) === Updater::STABILITY_STABLE From c04e65474d73cadf5a89b8f0c78c2f6da93e2466 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sun, 18 May 2025 16:52:12 +0200 Subject: [PATCH 126/130] check update requirements in healthcheck and get update endpoints --- .../src/Controller/UpdateController.php | 2 +- .../com_joomlaupdate/src/Model/UpdateModel.php | 18 ++++++++++++++++++ .../src/View/Healthcheck/JsonapiView.php | 18 ++++++++++++------ .../src/View/Updates/JsonapiView.php | 10 ++++++++-- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 3fc8e3895d432..73dd6f51eb054 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -735,7 +735,7 @@ public function healthstatus() $params = ComponentHelper::getParams('com_joomlaupdate'); // Edge case: the current state requires the registration, i.e. because it's a new installation - $registrationState = AutoupdateRegisterState::tryFrom($params->get('autoupdate_status', '')); + $registrationState = AutoupdateRegisterState::tryFrom($params->get('autoupdate_status', 0)); if ( $this->app->getIdentity()->authorise('core.admin', 'com_joomlaupdate') diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index ad81c8685defe..270b0f46ab78e 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -500,6 +500,24 @@ public function getAutoUpdateVersion(): ?string return $updateInfo['latest'] ?? null; } + /** + * Check if the hard conditions for an update are met + * + * @return boolean + * + * @since __DEPLOY_VERSION__ + */ + public function getAutoUpdateRequirementsState(): bool + { + foreach ($this->getPhpOptions() as $option) { + if ($option->state !== true) { + return false; + } + } + + return true; + } + /** * Download file and request password/filesize information * diff --git a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php index b1ad43cb70c1b..947e97c8c9549 100644 --- a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php @@ -13,6 +13,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; use Joomla\CMS\Uri\Uri; +use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; use Joomla\Database\DatabaseInterface; use Tobscure\JsonApi\Resource; @@ -41,7 +42,7 @@ public function healthCheck() $data['id'] = 'healthcheck'; $element = (new Resource((object) $data, $this->serializer)) - ->fields(['healthcheck' => ['php_version', 'db_type', 'db_version', 'cms_version', 'server_os']]); + ->fields(['healthcheck' => ['php_version', 'db_type', 'db_version', 'cms_version', 'server_os', 'update_requirement_state']]); $this->getDocument()->setData($element); $this->getDocument()->addLink('self', Uri::current()); @@ -60,12 +61,17 @@ protected function getStatsData() { $db = Factory::getContainer()->get(DatabaseInterface::class); + /** @var UpdateModel $updateModel */ + $updateModel = Factory::getApplication()->bootComponent('com_joomlaupdate') + ->getMVCFactory()->createModel('Update', 'Administrator', ['ignore_request' => true]); + $data = [ - 'php_version' => PHP_VERSION, - 'db_type' => $db->name, - 'db_version' => $db->getVersion(), - 'cms_version' => JVERSION, - 'server_os' => php_uname('s') . ' ' . php_uname('r'), + 'php_version' => PHP_VERSION, + 'db_type' => $db->name, + 'db_version' => $db->getVersion(), + 'cms_version' => JVERSION, + 'server_os' => php_uname('s') . ' ' . php_uname('r'), + 'update_requirement_state' => $updateModel->getAutoUpdateRequirementsState() ]; // Check if we have a MariaDB version string and extract the proper version from it diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index 1857e64c4ba0a..07bb09377870f 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -38,8 +38,6 @@ class JsonapiView extends BaseApiView */ public function getUpdate() { - $params = ComponentHelper::getParams('com_joomlaupdate'); - /** * @var UpdateModel $model */ @@ -51,6 +49,14 @@ public function getUpdate() $latestVersion = null; } + // Check pre-update states, unset update if not matched + $preUpdateState = $model->getAutoUpdateRequirementsState(); + + if (!$preUpdateState) { + $latestVersion = null; + } + + // Prepare response $element = (new Resource((object) ['availableUpdate' => $latestVersion, 'id' => 'getUpdate'], $this->serializer)) ->fields(['updates' => ['availableUpdate']]); From 654e01de44017970a49af28ade200323bd358ce7 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sun, 18 May 2025 17:00:05 +0200 Subject: [PATCH 127/130] add cache purger --- .../components/com_joomlaupdate/src/Model/UpdateModel.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index 270b0f46ab78e..337195d7639ed 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -560,6 +560,9 @@ public function prepareAutoUpdate(string $targetVersion): array */ public function changeAutoUpdateRegistration(AutoupdateRegisterState $targetState) { + // Purge cache - this makes sure that the changed status will already be available if the health check is performed + $this->cleanCache('_system'); + // Prepare connection $http = HttpFactory::getHttp(); From dac1d4384035c7bc6eaeb2910aa641119794f54c Mon Sep 17 00:00:00 2001 From: David Jardin Date: Sun, 18 May 2025 17:09:11 +0200 Subject: [PATCH 128/130] cs fix --- .../com_joomlaupdate/src/View/Healthcheck/JsonapiView.php | 2 +- .../com_joomlaupdate/src/View/Updates/JsonapiView.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php index 947e97c8c9549..4c67e5da13558 100644 --- a/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Healthcheck/JsonapiView.php @@ -71,7 +71,7 @@ protected function getStatsData() 'db_version' => $db->getVersion(), 'cms_version' => JVERSION, 'server_os' => php_uname('s') . ' ' . php_uname('r'), - 'update_requirement_state' => $updateModel->getAutoUpdateRequirementsState() + 'update_requirement_state' => $updateModel->getAutoUpdateRequirementsState(), ]; // Check if we have a MariaDB version string and extract the proper version from it diff --git a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php index 07bb09377870f..782ce99b42018 100644 --- a/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php +++ b/api/components/com_joomlaupdate/src/View/Updates/JsonapiView.php @@ -10,7 +10,6 @@ namespace Joomla\Component\Joomlaupdate\Api\View\Updates; -use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; use Joomla\CMS\Plugin\PluginHelper; From d169a3594b781e79e2ccc67ba86c602aabf428aa Mon Sep 17 00:00:00 2001 From: David Jardin Date: Mon, 19 May 2025 12:59:05 +0200 Subject: [PATCH 129/130] fix email --- administrator/language/en-GB/com_joomlaupdate.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index c1b1c5b4b6a18..0d0e09e03770e 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -93,7 +93,7 @@ COM_JOOMLAUPDATE_UPDATE_CHECK="Update Check" COM_JOOMLAUPDATE_UPDATE_CONFIRM_BACKUP="I'm aware that a backup before any update is highly recommended." COM_JOOMLAUPDATE_UPDATE_EMPTYSTATE_TITLE="Update your site to \"Joomla! %s\"" COM_JOOMLAUPDATE_UPDATE_EMPTYSTATE_BUTTON_ADD="Start update" -COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile '/administrator/logs/joomla_update.php' for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" +COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n\n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site could not be updated from {OLDVERSION} to {NEWVERSION}.\nPlease check the logfile '/administrator/logs/joomla_update.php' for further debugging information.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and trying to install such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT="Joomla! update failed {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATE_LOG_CLEANUP="Cleaning up after installation." COM_JOOMLAUPDATE_UPDATE_LOG_COMPLETE="Update to version %s is complete." @@ -110,7 +110,7 @@ COM_JOOMLAUPDATE_MAIL_UPDATE_FAILED_TITLE="Automated Joomla Update Failed" COM_JOOMLAUPDATE_MAIL_UPDATE_SUCCESS_DESC="Send to the site administrators if an Automated Joomla Update succeeded." COM_JOOMLAUPDATE_MAIL_UPDATE_SUCCESS_TITLE="Automated Joomla Update Succeeded" COM_JOOMLAUPDATE_UPDATE_LOGGING_TEST_FAIL="Logging does not work. Make sure the log folder is writable, and try again. The logging test failed with message: %s" -COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site has been successfully automatically updated from {OLDVERSION} to {NEWVERSION}.\nPlease check your site for any unexpected behavior or malfunctions.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and the installation of such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" +COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY="This email IS NOT sent by the Joomla! project. It is sent automatically by your own site,\n{SITENAME} - {URL} \n\n================================================================================\nUPDATE INFORMATION\n================================================================================\nYour site has been successfully automatically updated from {OLDVERSION} to {NEWVERSION}.\nPlease check your site for any unexpected behavior or malfunctions.\nThis email is sent to you by your site.\nThe Joomla! project will never contact you directly.\n================================================================================\nWHY AM I RECEIVING THIS EMAIL?\n================================================================================\nThis email has been automatically sent by Joomla!, the software which powers your site.\nYou have enabled automatic updates in your site and the installation of such an update triggers this message.\nIf you do not understand what Joomla! is and what you need to do please do not contact the Joomla! project.\nThey are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site.\n================================================================================\nWHO SENT ME THIS EMAIL?\n================================================================================\nThis email is sent to you by your own site, {SITENAME}" COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT="Joomla! updated successfully at {SITENAME} – {URL}" COM_JOOMLAUPDATE_UPDATING_HEAD="Update in progress" COM_JOOMLAUPDATE_UPDATING_INPROGRESS="Please wait; Joomla is being updated. This may take a while." From de781d9f647b5374f7b7fe1ebe921ef2ee097ca8 Mon Sep 17 00:00:00 2001 From: David Jardin Date: Mon, 19 May 2025 16:33:41 +0200 Subject: [PATCH 130/130] fix default config state --- administrator/components/com_joomlaupdate/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_joomlaupdate/config.xml b/administrator/components/com_joomlaupdate/config.xml index 2d8fef06e2b87..4d8bcbfcdc7b5 100644 --- a/administrator/components/com_joomlaupdate/config.xml +++ b/administrator/components/com_joomlaupdate/config.xml @@ -81,7 +81,7 @@ type="radio" label="COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_LABEL" description="COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_DESC" - default="1" + default="0" layout="joomla.form.field.radio.switcher" showon="updatesource:default[AND]minimum_stability:4" validate="options"