@@ -43,6 +43,50 @@ class JoomlaInstallerScript
4343 */
4444 protected $ fromVersion = null ;
4545
46+ /**
47+ * Callback for collecting errors. Like function(string $context, \Throwable $error){};
48+ *
49+ * @var callable
50+ *
51+ * @since __DEPLOY_VERSION__
52+ */
53+ protected $ errorCollector ;
54+
55+ /**
56+ * Set the callback for collecting errors.
57+ *
58+ * @param callable $callback The callback Like function(string $context, \Throwable $error){};
59+ *
60+ * @return void
61+ *
62+ * @since __DEPLOY_VERSION__
63+ */
64+ public function setErrorCollector (callable $ callback )
65+ {
66+ $ this ->errorCollector = $ callback ;
67+ }
68+
69+ /**
70+ * Collect errors.
71+ *
72+ * @param string $context A context/place where error happened
73+ * @param \Throwable $error The error that occurred
74+ *
75+ * @return void
76+ *
77+ * @since __DEPLOY_VERSION__
78+ */
79+ protected function collectError (string $ context , \Throwable $ error )
80+ {
81+ // The errorCollector are required
82+ // However when someone already running the script manually the code may fail.
83+ if ($ this ->errorCollector ) {
84+ call_user_func ($ this ->errorCollector , $ context , $ error );
85+ } else {
86+ Log::add ($ error ->getMessage (), Log::ERROR , 'Update ' );
87+ }
88+ }
89+
4690 /**
4791 * Function to act prior to installation process begins
4892 *
@@ -82,27 +126,45 @@ public function preflight($action, $installer)
82126 */
83127 public function update ($ installer )
84128 {
85- $ options ['format ' ] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE} ' ;
86- $ options ['text_file ' ] = 'joomla_update.php ' ;
87-
88- Log::addLogger ($ options , Log::INFO , ['Update ' , 'databasequery ' , 'jerror ' ]);
89-
129+ // Uninstall plugins before removing their files and folders
90130 try {
91131 Log::add (Text::_ ('COM_JOOMLAUPDATE_UPDATE_LOG_DELETE_FILES ' ), Log::INFO , 'Update ' );
92132 } catch (RuntimeException $ exception ) {
93133 // Informational log only
94134 }
95135
96136 // Uninstall extensions before removing their files and folders
97- $ this ->uninstallExtensions ();
98-
99- // This needs to stay for 2.5 update compatibility
100- $ this ->deleteUnexistingFiles ();
101- $ this ->updateManifestCaches ();
102- $ this ->updateDatabase ();
103- $ this ->updateAssets ($ installer );
104- $ this ->clearStatsCache ();
105- $ this ->cleanJoomlaCache ();
137+ try {
138+ Log::add (Text::_ ('COM_JOOMLAUPDATE_UPDATE_LOG_UNINSTALL_EXTENSIONS ' ), Log::INFO , 'Update ' );
139+ $ this ->uninstallExtensions ();
140+ } catch (\Throwable $ e ) {
141+ $ this ->collectError ('uninstallExtensions ' , $ e );
142+ }
143+
144+ // Remove old files
145+ try {
146+ Log::add (Text::_ ('COM_JOOMLAUPDATE_UPDATE_LOG_DELETE_FILES ' ), Log::INFO , 'Update ' );
147+ $ this ->deleteUnexistingFiles ();
148+ } catch (\Throwable $ e ) {
149+ $ this ->collectError ('deleteUnexistingFiles ' , $ e );
150+ }
151+
152+ // Further update
153+ try {
154+ $ this ->updateManifestCaches ();
155+ $ this ->updateDatabase ();
156+ $ this ->updateAssets ($ installer );
157+ $ this ->clearStatsCache ();
158+ } catch (\Throwable $ e ) {
159+ $ this ->collectError ('Further update ' , $ e );
160+ }
161+
162+ // Clean cache
163+ try {
164+ $ this ->cleanJoomlaCache ();
165+ } catch (\Throwable $ e ) {
166+ $ this ->collectError ('cleanJoomlaCache ' , $ e );
167+ }
106168 }
107169
108170 /**
@@ -127,7 +189,7 @@ protected function clearStatsCache()
127189 ->where ($ db ->quoteName ('element ' ) . ' = ' . $ db ->quote ('stats ' ))
128190 )->loadResult ();
129191 } catch (Exception $ e ) {
130- echo Text:: sprintf ( ' JLIB_DATABASE_ERROR_FUNCTION_FAILED ' , $ e -> getCode () , $ e-> getMessage ()) . ' <br> ' ;
192+ $ this -> collectError ( __METHOD__ , $ e) ;
131193
132194 return ;
133195 }
@@ -151,7 +213,7 @@ protected function clearStatsCache()
151213 try {
152214 $ db ->setQuery ($ query )->execute ();
153215 } catch (Exception $ e ) {
154- echo Text:: sprintf ( ' JLIB_DATABASE_ERROR_FUNCTION_FAILED ' , $ e -> getCode () , $ e-> getMessage ()) . ' <br> ' ;
216+ $ this -> collectError ( __METHOD__ , $ e) ;
155217
156218 return ;
157219 }
@@ -183,7 +245,7 @@ protected function updateDatabaseMysql()
183245 try {
184246 $ results = $ db ->loadObjectList ();
185247 } catch (Exception $ e ) {
186- echo Text:: sprintf ( ' JLIB_DATABASE_ERROR_FUNCTION_FAILED ' , $ e -> getCode () , $ e-> getMessage ()) . ' <br> ' ;
248+ $ this -> collectError ( __METHOD__ , $ e) ;
187249
188250 return ;
189251 }
@@ -198,7 +260,7 @@ protected function updateDatabaseMysql()
198260 try {
199261 $ db ->execute ();
200262 } catch (Exception $ e ) {
201- echo Text:: sprintf ( ' JLIB_DATABASE_ERROR_FUNCTION_FAILED ' , $ e -> getCode () , $ e-> getMessage ()) . ' <br> ' ;
263+ $ this -> collectError ( __METHOD__ , $ e) ;
202264
203265 return ;
204266 }
@@ -233,12 +295,12 @@ protected function uninstallExtensions()
233295 * 'pre_function' => Name of an optional migration function to be called before
234296 * uninstalling, `null` if not used.
235297 */
236- ['type ' => 'plugin ' , 'element ' => 'demotasks ' , 'folder ' => 'task ' , 'client_id ' => 0 , 'pre_function ' => null ],
237- ['type ' => 'plugin ' , 'element ' => 'compat ' , 'folder ' => 'system ' , 'client_id ' => 0 , 'pre_function ' => 'migrateCompatPlugin ' ],
238- ['type ' => 'plugin ' , 'element ' => 'logrotation ' , 'folder ' => 'system ' , 'client_id ' => 0 , 'pre_function ' => 'migrateLogRotationPlugin ' ],
239- ['type ' => 'plugin ' , 'element ' => 'recaptcha ' , 'folder ' => 'captcha ' , 'client_id ' => 0 , 'pre_function ' => null ],
240- ['type ' => 'plugin ' , 'element ' => 'sessiongc ' , 'folder ' => 'system ' , 'client_id ' => 0 , 'pre_function ' => 'migrateSessionGCPlugin ' ],
241- ['type ' => 'plugin ' , 'element ' => 'updatenotification ' , 'folder ' => 'system ' , 'client_id ' => 0 , 'pre_function ' => 'migrateUpdatenotificationPlugin ' ],
298+ ['type ' => 'plugin ' , 'element ' => 'demotasks ' , 'folder ' => 'task ' , 'client_id ' => 0 , 'pre_function ' => null ],
299+ ['type ' => 'plugin ' , 'element ' => 'compat ' , 'folder ' => 'system ' , 'client_id ' => 0 , 'pre_function ' => 'migrateCompatPlugin ' ],
300+ ['type ' => 'plugin ' , 'element ' => 'logrotation ' , 'folder ' => 'system ' , 'client_id ' => 0 , 'pre_function ' => 'migrateLogRotationPlugin ' ],
301+ ['type ' => 'plugin ' , 'element ' => 'recaptcha ' , 'folder ' => 'captcha ' , 'client_id ' => 0 , 'pre_function ' => null ],
302+ ['type ' => 'plugin ' , 'element ' => 'sessiongc ' , 'folder ' => 'system ' , 'client_id ' => 0 , 'pre_function ' => 'migrateSessionGCPlugin ' ],
303+ ['type ' => 'plugin ' , 'element ' => 'updatenotification ' , 'folder ' => 'system ' , 'client_id ' => 0 , 'pre_function ' => 'migrateUpdatenotificationPlugin ' ],
242304 ];
243305
244306 $ db = Factory::getDbo ();
@@ -477,7 +539,7 @@ protected function updateManifestCaches()
477539 try {
478540 $ extensions = $ db ->loadObjectList ();
479541 } catch (Exception $ e ) {
480- echo Text:: sprintf ( ' JLIB_DATABASE_ERROR_FUNCTION_FAILED ' , $ e -> getCode () , $ e-> getMessage ()) . ' <br> ' ;
542+ $ this -> collectError ( __METHOD__ , $ e) ;
481543
482544 return ;
483545 }
@@ -487,7 +549,10 @@ protected function updateManifestCaches()
487549
488550 foreach ($ extensions as $ extension ) {
489551 if (!$ installer ->refreshManifestCache ($ extension ->extension_id )) {
490- echo Text::sprintf ('FILES_JOOMLA_ERROR_MANIFEST ' , $ extension ->type , $ extension ->element , $ extension ->name , $ extension ->client_id ) . '<br> ' ;
552+ $ this ->collectError (
553+ __METHOD__ ,
554+ new \Exception (Text::sprintf ('FILES_JOOMLA_ERROR_MANIFEST ' , $ extension ->type , $ extension ->element , $ extension ->name , $ extension ->client_id ))
555+ );
491556 }
492557 }
493558 }
@@ -2346,6 +2411,8 @@ public function updateAssets($installer)
23462411 $ asset ->setLocation (1 , 'last-child ' );
23472412
23482413 if (!$ asset ->store ()) {
2414+ $ this ->collectError (__METHOD__ , new \Exception ($ asset ->getError (true )));
2415+
23492416 // Install failed, roll back changes
23502417 $ installer ->abort (Text::sprintf ('JLIB_INSTALLER_ABORT_COMP_INSTALL_ROLLBACK ' , $ asset ->getError (true )));
23512418
@@ -2552,6 +2619,9 @@ private function migratePrivacyconsentConfiguration(): bool
25522619 return false ;
25532620 }
25542621
2622+ // Refresh versionable assets cache.
2623+ Factory::getApplication ()->flushAssets ();
2624+
25552625 return true ;
25562626 }
25572627
@@ -2670,7 +2740,7 @@ private function setGuidedToursUid()
26702740 {
26712741 /** @var \Joomla\Component\Cache\Administrator\Model\CacheModel $model */
26722742 $ model = Factory::getApplication ()->bootComponent ('com_guidedtours ' )->getMVCFactory ()
2673- ->createModel ('Tours ' , 'Administrator ' , ['ignore_request ' => true ]);
2743+ ->createModel ('Tours ' , 'Administrator ' , ['ignore_request ' => true ]);
26742744
26752745 $ items = $ model ->getItems ();
26762746
0 commit comments