2018-10-06 00:53:13 +02:00
< ? php
namespace Friendica\Core ;
use Friendica\Database\DBStructure ;
class Update
{
2018-10-14 13:19:37 +02:00
const SUCCESS = 0 ;
const FAILED = 1 ;
2018-10-14 13:26:53 +02:00
/**
* @ brief Function to check if the Database structure needs an update .
*
* @ param boolean $via_worker boolean Is the check run via the worker ?
*/
public static function check ( $via_worker )
{
$build = Config :: get ( 'system' , 'build' );
if ( empty ( $build )) {
Config :: set ( 'system' , 'build' , DB_UPDATE_VERSION - 1 );
$build = DB_UPDATE_VERSION - 1 ;
}
// We don't support upgrading from very old versions anymore
if ( $build < NEW_UPDATE_ROUTINE_VERSION ) {
die ( 'You try to update from a version prior to database version 1170. The direct upgrade path is not supported. Please update to version 3.5.4 before updating to this version.' );
}
if ( $build < DB_UPDATE_VERSION ) {
// When we cannot execute the database update via the worker, we will do it directly
if ( ! Worker :: add ( PRIORITY_CRITICAL , 'DBUpdate' ) && $via_worker ) {
self :: run ();
}
}
}
2018-10-06 00:53:13 +02:00
/**
* Automatic database updates
*/
public static function run ()
{
$build = Config :: get ( 'system' , 'build' );
if ( empty ( $build ) || ( $build > DB_UPDATE_VERSION )) {
$build = DB_UPDATE_VERSION - 1 ;
Config :: set ( 'system' , 'build' , $build );
}
if ( $build != DB_UPDATE_VERSION ) {
require_once 'update.php' ;
$stored = intval ( $build );
$current = intval ( DB_UPDATE_VERSION );
if ( $stored < $current ) {
Config :: load ( 'database' );
// Compare the current structure with the defined structure
2018-10-06 20:38:35 +02:00
if ( Lock :: acquire ( 'dbupdate' )) {
// run the pre_update_nnnn functions in update.php
for ( $x = $stored + 1 ; $x <= $current ; $x ++ ) {
$r = self :: runUpdateFunction ( $x , 'pre_update' );
if ( ! $r ) {
break ;
}
2018-10-06 00:53:13 +02:00
}
2018-10-06 20:38:35 +02:00
// update the structure in one call
$retval = DBStructure :: update ( false , true );
if ( $retval ) {
DBStructure :: updateFail (
DB_UPDATE_VERSION ,
$retval
);
Lock :: release ( 'dbupdate' );
return ;
} else {
2018-10-07 10:42:14 +02:00
Config :: set ( 'database' , 'last_successful_update' , $current );
Config :: set ( 'database' , 'last_successful_update_time' , time ());
2018-10-06 20:38:35 +02:00
}
2018-10-06 00:53:13 +02:00
2018-10-06 20:38:35 +02:00
// run the update_nnnn functions in update.php
for ( $x = $stored + 1 ; $x <= $current ; $x ++ ) {
$r = self :: runUpdateFunction ( $x , 'update' );
if ( ! $r ) {
break ;
}
2018-10-06 00:53:13 +02:00
}
2018-10-06 20:38:35 +02:00
Lock :: release ( 'dbupdate' );
2018-10-06 00:53:13 +02:00
}
}
}
}
/**
* Executes a specific update function
*
* @ param int $x the DB version number of the function
* @ param string $prefix the prefix of the function ( update , pre_update )
*
* @ return bool true , if the update function worked
*/
public static function runUpdateFunction ( $x , $prefix )
{
$funcname = $prefix . '_' . $x ;
if ( function_exists ( $funcname )) {
// There could be a lot of processes running or about to run.
// We want exactly one process to run the update command.
// So store the fact that we're taking responsibility
// after first checking to see if somebody else already has.
// If the update fails or times-out completely you may need to
// delete the config entry to try again.
2018-10-06 20:38:35 +02:00
if ( Lock :: acquire ( 'dbupdate_function' )) {
// call the specific update
$retval = $funcname ();
2018-10-06 00:53:13 +02:00
2018-10-06 20:38:35 +02:00
if ( $retval ) {
//send the administrator an e-mail
DBStructure :: updateFail (
$x ,
L10n :: t ( 'Update %s failed. See error logs.' , $x )
);
Lock :: release ( 'dbupdate_function' );
return false ;
} else {
Config :: set ( 'database' , 'last_successful_update_function' , $funcname );
Config :: set ( 'database' , 'last_successful_update_function_time' , time ());
if ( $prefix == 'update' ) {
Config :: set ( 'system' , 'build' , $x );
}
Lock :: release ( 'dbupdate_function' );
return true ;
}
2018-10-06 00:53:13 +02:00
}
} else {
2018-10-06 20:38:35 +02:00
logger ( 'Skipping \'' . $funcname . '\' without executing' , LOGGER_DEBUG );
Config :: set ( 'database' , 'last_successful_update_function' , $funcname );
Config :: set ( 'database' , 'last_successful_update_function_time' , time ());
2018-10-06 00:53:13 +02:00
if ( $prefix == 'update' ) {
Config :: set ( 'system' , 'build' , $x );
}
return true ;
}
}
2018-10-06 20:38:35 +02:00
}