2002-03-03 22:47:30 +01:00
< ? php
2009-05-28 13:33:30 +02:00
/**
* EGroupware setup - update / install an EGroupware instance
*
* @ link http :// www . egroupware . org
* @ author Miles Lott < milos @ groupwhere . org >
* @ copyright 2001 - 2004 Miles Lott < milos @ groupwhere . org >
* @ author Ralf Becker < RalfBecker - AT - outdoor - training . de >
* Upgrade process rewritten by < RalfBecker @ outdoor - training . de > to no longer require tables_baseline files and delta - upgrades
* @ package setup
* @ license http :// opensource . org / licenses / gpl - license . php GPL - GNU General Public License
* @ version $Id $
*/
2016-02-20 21:27:17 +01:00
use EGroupware\Api ;
2009-05-28 13:33:30 +02:00
/**
* Update / install an EGroupware instance
*
* app status values :
* U Upgrade required / available
* R upgrade in pRogress
* C upgrade Completed successfully
* D Dependency failure
2011-05-04 15:45:01 +02:00
* P Post - install dependency failure
2009-05-28 13:33:30 +02:00
* F upgrade Failed
* V Version mismatch at end of upgrade ( Not used , proposed only )
* M Missing files at start of upgrade ( Not used , proposed only )
*/
class setup_process
{
var $tables ;
var $updateincluded = array ();
/**
* Target version of a complete upgrade , set by pass ()
*
* @ var string
*/
var $api_version_target ;
2021-12-04 08:55:10 +01:00
/**
* @ var Api\Db\Schema
*/
protected $oProc ;
/**
* @ var Api\Db
*/
protected $db ;
2009-05-28 13:33:30 +02:00
/**
* create schema_proc object
*/
function init_process ()
{
2021-12-04 08:55:10 +01:00
if ( empty ( $GLOBALS [ 'egw_setup' ] -> oProc ))
{
$this -> oProc = $GLOBALS [ 'egw_setup' ] -> oProc = new Api\Db\Schema ();
}
else
{
$this -> oProc = $GLOBALS [ 'egw_setup' ] -> oProc ;
}
$this -> db = $this -> oProc -> m_odb ? ? $GLOBALS [ 'egw_setup' ] -> db ;
2009-05-28 13:33:30 +02:00
}
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
/**
* the mother of all multipass upgrade parental loop functions
*
2016-04-02 21:55:08 +02:00
* @ param array $setup_info array of application info from setup . inc . php files
2009-05-28 13:33:30 +02:00
* @ param string $type = 'new' defaults to new ( install ), could also be 'upgrade'
* @ param boolean $DEBUG = false print debugging info
2016-04-02 21:55:08 +02:00
* @ param boolean $force_en = false install english language files , not used anymore
2009-05-28 13:33:30 +02:00
* @ param string $system_charset = null charset to use
* @ param array $preset_config = array ()
*/
function pass ( array $setup_info , $method = 'new' , $DEBUG = False , $force_en = False , $preset_config = array ())
{
2016-04-02 21:55:08 +02:00
unset ( $force_en ); // no longer used
2009-05-28 13:33:30 +02:00
if ( ! $method )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
return False ;
2002-03-03 22:47:30 +01:00
}
2016-04-02 21:55:08 +02:00
// update to 16.x with no api installed yet
if ( $method == 'upgrade' && ! isset ( $setup_info [ 'api' ][ 'currentver' ]))
{
// remove api dependency
unset ( $setup_info [ 'phpgwapi' ][ 'depends' ][ 'api' ]);
$pass [ 'phpgwapi' ] = $setup_info [ 'phpgwapi' ];
$pass [ 'emailadmin' ] = $setup_info [ 'emailadmin' ];
$pass [ 'api' ] = $setup_info [ 'api' ];
// mark api as already installed in version 14.3.907
$setup_info [ 'api' ][ 'version' ] = $setup_info [ 'api' ][ 'currentversion' ] = '14.3.907' ;
$GLOBALS [ 'egw_setup' ] -> register_app ( 'api' , 99 , $setup_info );
$setup_info [ 'api' ][ 'version' ] = $pass [ 'api' ][ 'version' ];
}
// new install or upgrade after 16.x api is installed
else
{
$pass [ 'api' ] = $setup_info [ 'api' ];
2016-05-03 00:26:40 +02:00
if ( file_exists ( EGW_SERVER_ROOT . '/phpgwapi' ) && is_readable ( EGW_SERVER_ROOT . '/phpgwapi' ))
{
$pass [ 'phpgwapi' ] = $setup_info [ 'phpgwapi' ];
}
2016-06-03 16:09:49 +02:00
// ignore emailadmin, it's only there for updates
unset ( $setup_info [ 'emailadmin' ]);
2016-04-02 21:55:08 +02:00
}
2009-05-28 13:33:30 +02:00
$pass [ 'admin' ] = $setup_info [ 'admin' ];
$pass [ 'preferences' ] = $setup_info [ 'preferences' ];
2016-05-03 00:26:40 +02:00
if ( file_exists ( EGW_SERVER_ROOT . '/etemplate' ))
{
$pass [ 'etemplate' ] = $setup_info [ 'etemplate' ]; // helps to minimize passes, as many apps depend on it
}
2016-04-02 21:55:08 +02:00
$this -> api_version_target = $setup_info [ 'api' ][ 'version' ];
2009-05-28 13:33:30 +02:00
$i = 1 ;
$passed = array ();
$passing = array ();
2019-08-15 10:31:43 +02:00
$pass_string = implode ( ':' , array_keys ( $pass ));
$passing_string = implode ( ':' , array_keys ( $passing ));
2009-05-28 13:33:30 +02:00
while ( $pass_string != $passing_string )
2002-03-03 22:47:30 +01:00
{
$passing = array ();
2009-05-28 13:33:30 +02:00
if ( $DEBUG ) { echo '<br>process->pass(): #' . $i . ' for ' . $method . ' processing' . " \n " ; }
2016-04-02 21:55:08 +02:00
// Check current versions and dependencies
$setup_info = $GLOBALS [ 'egw_setup' ] -> detection -> check_depends (
$GLOBALS [ 'egw_setup' ] -> detection -> compare_versions (
$GLOBALS [ 'egw_setup' ] -> detection -> get_db_versions ( $setup_info ), true ));
// stuff the rest of the apps, but only those with available upgrades
2009-05-28 13:33:30 +02:00
foreach ( $setup_info as $key => $value )
2002-03-03 22:47:30 +01:00
{
2010-09-08 14:24:05 +02:00
// check if app is either installed or supports the used database
if ( ! isset ( $value [ 'currentver' ]) && isset ( $value [ 'only_db' ]) && (
2009-05-28 13:33:30 +02:00
is_array ( $value [ 'only_db' ]) && ! in_array ( $GLOBALS [ 'egw_setup' ] -> db -> Type , $value [ 'only_db' ]) ||
! is_array ( $value [ 'only_db' ]) && $GLOBALS [ 'egw_setup' ] -> db -> Type != $value [ 'only_db' ]))
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
continue ; // app does not support this db-type, dont try installing it
}
2016-04-02 21:55:08 +02:00
if ( /*$value['name'] != 'phpgwapi' &&*/ $value [ 'status' ] == 'U' )
2009-05-28 13:33:30 +02:00
{
if ( $passed [ $value [ 'name' ]][ 'status' ] != 'F' && $passed [ $value [ 'name' ]][ 'status' ] != 'C' )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$pass [ $value [ 'name' ]] = $setup_info [ $value [ 'name' ]];
2002-03-03 22:47:30 +01:00
}
}
2009-05-28 13:33:30 +02:00
}
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
switch ( $method )
{
case 'new' :
2016-05-03 00:26:40 +02:00
if ( empty ( $GLOBALS [ 'egw_info' ][ 'server' ][ 'temp_dir' ]))
{
$GLOBALS [ 'egw_info' ][ 'server' ][ 'temp_dir' ] = sys_get_temp_dir ();
}
2009-05-28 13:33:30 +02:00
/* Create tables and insert new records for each app in this list */
2016-04-02 21:55:08 +02:00
$passing_c = $this -> current ( $pass , $DEBUG );
2016-05-03 00:26:40 +02:00
if ( isset ( $pass [ 'api' ])) $this -> save_minimal_config ( $preset_config );
2016-04-02 21:55:08 +02:00
$passing = $this -> default_records ( $passing_c , $DEBUG );
2009-05-28 13:33:30 +02:00
break ;
case 'upgrade' :
/* Run upgrade scripts on each app in the list */
$passing = $this -> upgrade ( $pass , $DEBUG );
//_debug_array($pass);exit;
break ;
default :
/* What the heck are you doing? */
return False ;
}
$pass = array ();
foreach ( $passing as $key => $value )
{
if ( $value [ 'status' ] == 'C' )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$passed [ $value [ 'name' ]] = $passing [ $value [ 'name' ]];
if ( $DEBUG ) { echo '<br>process->pass(): ' . $passed [ $value [ 'name' ]][ 'name' ] . ' install completed' . " \n " ; }
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
elseif ( $value [ 'status' ] == 'F' )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$setup_info [ $value [ 'name' ]] = $passing [ $value [ 'name' ]];
if ( $DEBUG ) { echo '<br>process->pass(): ' . $setup_info [ $value [ 'name' ]][ 'name' ] . ' install failed' . " \n " ; }
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
elseif ( $value [ 'status' ] == 'D' )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$pass [ $value [ 'name' ]] = $setup_info [ $value [ 'name' ]];
if ( $DEBUG ) { echo '<br>process->pass(): ' . $pass [ $value [ 'name' ]][ 'name' ] . ' fails dependency check on this pass' . " \n " ; }
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
else
2004-10-23 17:00:44 +02:00
{
2009-05-28 13:33:30 +02:00
$tmp = $passing [ $value [ 'name' ]][ 'name' ];
if ( $DEBUG ) { echo '<br>process->pass(): ' . $tmp . ' skipped on this pass' . " \n " ; }
2004-10-23 17:00:44 +02:00
}
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
$i ++ ;
if ( $i == 20 ) /* Then oops it broke */
{
echo '<br>Setup failure: excess looping in process->pass():' . " \n " ;
echo '<br>Pass:<br>' . " \n " ;
_debug_array ( $pass );
echo '<br>Passed:<br>' . " \n " ;
_debug_array ( $passed );
exit ;
}
2019-08-15 10:31:43 +02:00
$pass_string = implode ( ':' , array_keys ( $pass ));
$passing_string = implode ( ':' , array_keys ( $passing ));
2009-05-28 13:33:30 +02:00
}
2019-08-15 10:31:43 +02:00
// remove all apps which should be automatic deinstalled
if (( $deinstall = setup_cmd :: check_autodeinstall ()))
{
$this -> remove ( $deinstall , $setup_info , $DEBUG );
}
2014-06-25 14:43:11 +02:00
try {
2016-04-02 21:55:08 +02:00
// flush instance cache: also registers hooks and flushes image cache
Api\Cache :: flush ( Api\Cache :: INSTANCE );
2014-06-25 14:43:11 +02:00
}
catch ( Exception $e ) {
unset ( $e );
// ignore exception, as during a new install, there's no cache configured and therefore no need to unset
}
2009-05-28 13:33:30 +02:00
/* now return the list */
2016-04-02 21:55:08 +02:00
return array_merge ( $setup_info , $passed );
2009-05-28 13:33:30 +02:00
}
2003-10-04 15:24:34 +02:00
2009-05-28 13:33:30 +02:00
/**
* saves a minimal default config , so you get a running install without entering and saveing Step #2 config
*
2016-04-02 21:55:08 +02:00
* @ param array $preset_config = array ()
2009-05-28 13:33:30 +02:00
*/
function save_minimal_config ( array $preset_config = array ())
{
$is_windows = strtoupper ( substr ( PHP_OS , 0 , 3 )) == 'WIN' ;
2008-10-21 16:22:27 +02:00
2010-02-14 06:51:51 +01:00
$current_config [ 'site_title' ] = 'EGroupware' ;
2009-05-30 22:15:31 +02:00
$current_config [ 'hostname' ] = isset ( $_SERVER [ 'HTTP_HOST' ]) ? $_SERVER [ 'HTTP_HOST' ] : 'localhost' ;
2008-10-21 16:22:27 +02:00
2018-04-11 15:13:21 +02:00
// guessing the EGw url
2009-05-30 22:15:31 +02:00
if ( isset ( $_SERVER [ 'HTTP_HOST' ]))
{
$parts = explode ( '/' , $_SERVER [ 'PHP_SELF' ]);
array_pop ( $parts ); // remove config.php
array_pop ( $parts ); // remove setup
$current_config [ 'webserver_url' ] = implode ( '/' , $parts );
$egroupwareDirName = end ( $parts );
}
else // eg. cli install --> use defaults
{
$current_config [ 'webserver_url' ] = '/egroupware' ;
$egroupwareDirName = 'egroupware' ;
}
2009-10-12 09:39:47 +02:00
if ( ! $is_windows )
2009-05-30 22:15:31 +02:00
{
2009-05-28 13:33:30 +02:00
if ( @ is_dir ( '/tmp' ))
2007-12-13 03:41:55 +01:00
{
2009-05-28 13:33:30 +02:00
$current_config [ 'temp_dir' ] = '/tmp' ;
2004-10-23 17:00:44 +02:00
}
2009-05-28 13:33:30 +02:00
else
2003-10-04 15:24:34 +02:00
{
2009-05-28 13:33:30 +02:00
$current_config [ 'temp_dir' ] = '/path/to/temp/dir' ;
2003-10-04 15:24:34 +02:00
}
2009-05-28 13:33:30 +02:00
$current_config [ 'files_dir' ] = '/var/lib/' . $egroupwareDirName . '/' . $GLOBALS [ 'egw_setup' ] -> ConfigDomain . '/files' ;
$current_config [ 'backup_dir' ] = '/var/lib/' . $egroupwareDirName . '/' . $GLOBALS [ 'egw_setup' ] -> ConfigDomain . '/backup' ;
2010-02-14 06:51:51 +01:00
$current_config [ 'aspell_path' ] = '/usr/bin/aspell' ;
2003-10-04 15:24:34 +02:00
}
2009-05-28 13:33:30 +02:00
else
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
if ( @ is_dir ( 'c:\\windows\\temp' ))
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$current_config [ 'temp_dir' ] = 'c:\\windows\\temp' ;
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
else
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$current_config [ 'temp_dir' ] = 'c:\\path\\to\\temp\\dir' ;
2002-03-03 22:47:30 +01:00
}
2010-02-14 06:51:51 +01:00
$current_config [ 'files_dir' ] = 'C:\\Program Files\\' . $egroupwareDirName . '\\' . $GLOBALS [ 'egw_setup' ] -> ConfigDomain . '\\files' ;
$current_config [ 'backup_dir' ] = 'C:\\Program Files\\' . $egroupwareDirName . '\\' . $GLOBALS [ 'egw_setup' ] -> ConfigDomain . '\\backup' ;
2010-02-14 07:11:28 +01:00
$current_config [ 'aspell_path' ] = 'C:\\Program Files\\Aspell\\bin\\aspell.exe' ;
2010-02-14 06:51:51 +01:00
}
// only set aspell path, if it's installed
if ( ! is_executable ( $current_config [ 'aspell_path' ]))
{
unset ( $current_config [ 'aspell_path' ]);
2009-05-28 13:33:30 +02:00
}
2014-09-04 11:58:48 +02:00
// always enable browser based spellchecker
$current_config [ 'enabled_spellcheck' ] = 'YesBrowserBased' ;
2011-05-04 09:52:45 +02:00
2010-06-16 10:57:40 +02:00
// always enable history logging for calendar, addressbook and infolog
$current_config [ 'history' ] = 'history' ; // addressbook: only admin
$current_config [ 'calendar_delete_history' ] = 'history' ; // only admins
// infolog does NOT use config_app='phpgwapi', but 'infolog'
$GLOBALS [ 'egw_setup' ] -> db -> insert ( $GLOBALS [ 'egw_setup' ] -> config_table , array (
'config_value' => 'history_admin_delete' , // only admins
), array (
'config_app' => 'infolog' ,
'config_name' => 'history' ,
), __FILE__ , __LINE__ );
2011-05-04 09:52:45 +02:00
2010-06-10 07:55:15 +02:00
2009-05-28 13:33:30 +02:00
// RalfBecker: php.net recommend this for security reasons, it should be our default too
$current_config [ 'usecookies' ] = 'True' ;
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
if ( $GLOBALS [ 'egw_setup' ] -> system_charset )
{
$current_config [ 'system_charset' ] = $GLOBALS [ 'egw_setup' ] -> system_charset ;
2002-03-03 22:47:30 +01:00
}
2010-03-15 08:51:38 +01:00
// storing default timezone as server timezone
try
{
$tz = new DateTimeZone ( date_default_timezone_get ());
$current_config [ 'server_timezone' ] = $tz -> getName ();
}
catch ( Exception $e )
{
2016-04-02 21:55:08 +02:00
unset ( $e );
2010-03-15 08:51:38 +01:00
// do nothing if new DateTimeZone fails (eg. 'System/Localtime' returned), specially do NOT store it!
error_log ( __METHOD__ . " () NO valid 'date.timezone' set in your php.ini! " );
}
2009-05-28 13:33:30 +02:00
$current_config [ 'install_id' ] = md5 ( $_SERVER [ 'HTTP_HOST' ] . microtime ( true ) . $GLOBALS [ 'egw_setup' ] -> ConfigDomain );
2016-05-03 00:26:40 +02:00
$current_config [ 'postpone_statistics_submit' ] = time () + 2 * 30 * 86400 ; // ask user in 2 month from now, when he has something to report
2009-11-17 10:24:10 +01:00
2011-06-06 01:22:51 +02:00
// use securest password hash by default
2011-06-07 10:02:06 +02:00
require_once EGW_SERVER_ROOT . '/setup/inc/hook_config.inc.php' ; // for sql_passwdhashes, to get securest available password hash
2016-04-02 21:55:08 +02:00
$securest = null ;
2011-06-06 01:22:51 +02:00
sql_passwdhashes ( array (), true , $securest );
$current_config [ 'sql_encryption_type' ] = $current_config [ 'ldap_encryption_type' ] = $securest ;
2011-05-04 09:52:45 +02:00
2009-05-28 13:33:30 +02:00
if ( $preset_config )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$current_config = array_merge ( $current_config , $preset_config );
}
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
foreach ( $current_config as $name => $value )
{
2014-11-06 14:46:03 +01:00
$app = 'phpgwapi' ;
if ( $name == 'postpone_statistics_submit' )
{
$app = 'admin' ;
}
elseif ( strpos ( $name , '/' ) !== false )
{
list ( $app , $name ) = explode ( '/' , $name );
}
2009-05-28 13:33:30 +02:00
$GLOBALS [ 'egw_setup' ] -> db -> insert ( $GLOBALS [ 'egw_setup' ] -> config_table , array (
'config_value' => $value ,
), array (
2014-11-06 14:46:03 +01:00
'config_app' => $app ,
2009-05-28 13:33:30 +02:00
'config_name' => $name ,
), __FILE__ , __LINE__ );
}
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
// so the default_records use the current data
2013-10-15 11:25:49 +02:00
$GLOBALS [ 'egw_info' ][ 'server' ] = array_merge (( array ) $GLOBALS [ 'egw_info' ][ 'server' ], $current_config );
2016-04-02 21:55:08 +02:00
Api\Cache :: flush (); // flush whole instance cache
2016-05-01 17:56:49 +02:00
Api\Config :: init_static (); // flush internal cache of Api\Config class
2009-05-28 13:33:30 +02:00
$GLOBALS [ 'egw_setup' ] -> setup_account_object ( $current_config );
}
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
/**
* drop tables per application , check that they are in the db first
*
* @ param $setup_info array of application info from setup . inc . php files , etc .
*/
function droptables ( array $setup_info , $DEBUG = False )
{
2021-12-04 08:55:10 +01:00
if ( ! $this -> oProc )
2009-05-28 13:33:30 +02:00
{
$this -> init_process ();
}
/* The following is built so below we won't try to drop a table that isn't there. */
2021-12-04 08:55:10 +01:00
$tables = $this -> db -> table_names ( true );
$views = $this -> db -> Link_ID -> MetaTables ( 'VIEWS' );
if ( ! is_array ( $setup_info ) || ! $tables && ! $views )
2009-05-28 13:33:30 +02:00
{
return $setup_info ; // nothing to do
}
foreach ( $setup_info as $app_name => $data )
{
2021-12-04 08:55:10 +01:00
// drop views first
foreach ( $data [ 'views' ] ? ? [] as $view )
2009-05-28 13:33:30 +02:00
{
2021-12-04 08:55:10 +01:00
if ( in_array ( $view , $views ))
2002-03-03 22:47:30 +01:00
{
2021-12-04 08:55:10 +01:00
if ( $DEBUG ){ echo '<br>process->droptables(): Dropping :' . $app_name . ' view: ' . $view ; }
$this -> db -> query ( " DROP VIEW $view " , __LINE__ , __FILE__ );
}
}
// drop them in reverse order, in case the have constrains
2022-04-01 13:38:18 +02:00
foreach ( array_reverse (( array )( $data [ 'tables' ] ? ? [])) as $table )
2021-12-04 08:55:10 +01:00
{
//echo $table;
if ( in_array ( $table , $tables ))
{
if ( $DEBUG ){ echo '<br>process->droptables(): Dropping :' . $app_name . ' table: ' . $table ; }
$this -> oProc -> DropTable ( $table );
// Update the array values for return below
$setup_info [ $app_name ][ 'status' ] = 'U' ;
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
}
}
/* Done, return current status */
return $setup_info ;
}
/**
* process current table setup in each application / setup dir
*
* @ param array $setup_info array of application info from setup . inc . php files , etc .
2016-04-02 21:55:08 +02:00
* @ param boolean $DEBUG = false output further diagnostics
2009-05-28 13:33:30 +02:00
* @ return array $setup_info
*/
function current ( array $setup_info , $DEBUG = False )
{
//echo __METHOD__; _debug_array($setup_info);
2021-12-04 08:55:10 +01:00
if ( ! isset ( $this -> oProc ))
2009-05-28 13:33:30 +02:00
{
$this -> init_process ();
}
foreach ( $setup_info as $appname => & $appdata )
{
$enabled = False ;
$apptitle = $appdata [ 'title' ];
if ( $DEBUG ) { echo '<br>process->current(): Incoming status: ' . $appname . ',status: ' . $appdata [ 'status' ]; }
2016-05-03 00:26:40 +02:00
$appdir = EGW_SERVER_ROOT . '/' . $appname . '/setup/' ;
2009-05-28 13:33:30 +02:00
2021-12-04 08:55:10 +01:00
if ( $appdata [ 'tables' ] && file_exists ( $appdir . 'tables_current.inc.php' ) && empty ( $appdata [ 'skip_create_tables' ]))
2009-05-28 13:33:30 +02:00
{
if ( $DEBUG ) { echo '<br>process->current(): Including: ' . $appdir . 'tables_current.inc.php' ; }
2016-04-02 21:55:08 +02:00
$phpgw_baseline = null ;
2009-05-28 13:33:30 +02:00
include ( $appdir . 'tables_current.inc.php' );
$ret = $this -> post_process ( $phpgw_baseline , $DEBUG );
if ( $ret )
2002-03-03 22:47:30 +01:00
{
2005-03-04 16:00:33 +01:00
if ( $GLOBALS [ 'egw_setup' ] -> app_registered ( $appname ))
2002-03-03 22:47:30 +01:00
{
2005-03-04 16:00:33 +01:00
$GLOBALS [ 'egw_setup' ] -> update_app ( $appname );
2002-03-03 22:47:30 +01:00
}
else
{
2009-05-28 13:33:30 +02:00
$GLOBALS [ 'egw_setup' ] -> register_app ( $appname );
2009-10-18 14:57:30 +02:00
$GLOBALS [ 'egw_setup' ] -> set_default_preferences ( $appname );
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
// Update the array values for return below
$appdata [ 'status' ] = 'C' ;
}
else
{
/* script processing failed */
if ( $DEBUG ) { echo '<br>process->current(): Failed for ' . $appname . ',status: ' . $appdata [ 'status' ]; }
$appdata [ 'status' ] = 'F' ;
2002-03-03 22:47:30 +01:00
}
}
2009-05-28 13:33:30 +02:00
else
{
if ( $DEBUG ) { echo '<br>process->current(): No current tables for ' . $apptitle . " \n " ; }
/*
Add the app , but disable it if it has tables defined .
A manual sql script install is needed , but we do add the hooks
*/
$enabled = 99 ;
2022-01-08 10:27:15 +01:00
if ( ! empty ( $appdata [ 'tables' ]) && empty ( $appdata [ 'skip_create_tables' ]))
2009-05-28 13:33:30 +02:00
{
$enabled = False ;
}
if ( $GLOBALS [ 'egw_setup' ] -> app_registered ( $appname ))
{
$GLOBALS [ 'egw_setup' ] -> update_app ( $appname );
}
else
{
$GLOBALS [ 'egw_setup' ] -> register_app ( $appname , $enabled );
2009-10-18 14:57:30 +02:00
$GLOBALS [ 'egw_setup' ] -> set_default_preferences ( $appname );
2009-05-28 13:33:30 +02:00
}
$appdata [ 'status' ] = 'C' ;
}
if ( $DEBUG ) { echo '<br>process->current(): Outgoing status: ' . $appname . ',status: ' . $appdata [ 'status' ]; }
2002-03-03 22:47:30 +01:00
}
2016-04-02 21:55:08 +02:00
// update hooks
Api\Hooks :: read ( true );
2009-05-28 13:33:30 +02:00
/* Done, return current status */
return $setup_info ;
}
/**
* process default_records . inc . php in each application / setup dir
*
* @ param array $setup_info array of application info from setup . inc . php files , etc .
2016-04-02 21:55:08 +02:00
* @ param boolean $DEBUG = false output further diagnostics
2009-05-28 13:33:30 +02:00
* @ return array $setup_info
*/
function default_records ( array $setup_info , $DEBUG = False )
{
//echo __METHOD__; _debug_array($setup_info);
2021-12-04 08:55:10 +01:00
if ( ! $this -> oProc )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$this -> init_process ();
}
foreach ( $setup_info as $appname => & $appdata )
{
2016-05-03 00:26:40 +02:00
$appdir = EGW_SERVER_ROOT . '/' . $appname . '/setup/' ;
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
if ( file_exists ( $appdir . 'default_records.inc.php' ))
{
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo '<br>process->default_records(): Including default records for ' . $appname . " \n " ;
2002-03-03 22:47:30 +01:00
}
2021-12-04 08:55:10 +01:00
$oProc = & $this -> oProc ; // to be compatible with old apps
2009-05-28 13:33:30 +02:00
include ( $appdir . 'default_records.inc.php' );
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
/* $appdata['status'] = 'C'; */
2002-03-03 22:47:30 +01:00
}
2016-04-02 21:55:08 +02:00
unset ( $appdata , $oProc );
2013-01-14 21:25:37 +01:00
// Clear categories cache in case app adds categories
2016-05-01 17:56:49 +02:00
Api\Categories :: invalidate_cache ();
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
/* Done, return current status */
return ( $setup_info );
}
/**
* process test_data . inc . php in each application / setup dir for developer tests
*
* This data should work with the baseline tables
*
* @ param array $setup_info array of application info from setup . inc . php files , etc .
2016-04-02 21:55:08 +02:00
* @ param boolean $DEBUG = false output further diagnostics
2009-05-28 13:33:30 +02:00
* @ return array $setup_info
*/
function test_data ( array $setup_info , $DEBUG = False )
{
2021-12-04 08:55:10 +01:00
if ( ! $this -> oProc )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$this -> init_process ();
}
foreach ( $setup_info as $appname => & $appdata )
{
2016-05-03 00:26:40 +02:00
$appdir = EGW_SERVER_ROOT . '/' . $appname . '/setup/' ;
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
if ( file_exists ( $appdir . 'test_data.inc.php' ))
{
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo '<br>process->test_data(): Including baseline test data for ' . $appname . " \n " ;
2002-03-03 22:47:30 +01:00
}
2021-12-04 08:55:10 +01:00
$this -> oProc -> m_odb -> transaction_begin ();
2009-05-28 13:33:30 +02:00
include ( $appdir . 'test_data.inc.php' );
2021-12-04 08:55:10 +01:00
$this -> oProc -> m_odb -> transaction_commit ();
2002-03-03 22:47:30 +01:00
}
}
2016-04-02 21:55:08 +02:00
unset ( $appdata );
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
/* Done, return current status */
return ( $setup_info );
}
/**
* process baseline table setup in each application / setup dir
*
* @ param array $setup_info array of application info from setup . inc . php files , etc .
2016-04-02 21:55:08 +02:00
* @ param boolean $DEBUG = false output further diagnostics
2009-05-28 13:33:30 +02:00
* @ return array $setup_info
*/
function baseline ( array $setup_info , $DEBUG = False )
{
2021-12-04 08:55:10 +01:00
if ( ! $this -> oProc )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$this -> init_process ();
}
foreach ( $setup_info as $appname => & $appdata )
{
2016-05-03 00:26:40 +02:00
$appdir = EGW_SERVER_ROOT . '/' . $appname . '/setup/' ;
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
if ( file_exists ( $appdir . 'tables_baseline.inc.php' ))
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo '<br>process->baseline(): Including baseline tables for ' . $appname . " \n " ;
2002-03-03 22:47:30 +01:00
}
2016-04-02 21:55:08 +02:00
$phpgw_baseline = null ;
2009-05-28 13:33:30 +02:00
include ( $appdir . 'tables_baseline.inc.php' );
2021-12-04 08:55:10 +01:00
$this -> oProc -> GenerateScripts ( $phpgw_baseline , $DEBUG );
2009-05-28 13:33:30 +02:00
$this -> post_process ( $phpgw_baseline , $DEBUG );
/* Update the array values for return below */
/* $setup_info[$key]['status'] = 'R'; */
}
else
{
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo '<br>process->baseline(): No baseline tables for ' . $appname . " \n " ;
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
//$setup_info[$key]['status'] = 'C';
2002-03-03 22:47:30 +01:00
}
}
2016-04-02 21:55:08 +02:00
unset ( $appdata );
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
/* Done, return current status */
return ( $setup_info );
}
/**
* process available upgrades in each application / setup dir
*
* @ param array $setup_info array of application info from setup . inc . php files , etc .
2016-04-02 21:55:08 +02:00
* @ param boolean $DEBUG = false output further diagnostics
2009-05-28 13:33:30 +02:00
* @ return array $setup_info
*/
function upgrade ( $setup_info , $DEBUG = False )
{
//echo __METHOD__; _debug_array($setup_info);
2021-12-04 08:55:10 +01:00
if ( ! $this -> oProc )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
$this -> init_process ();
}
2021-12-04 08:55:10 +01:00
$this -> oProc -> m_odb -> HaltOnError = 'yes' ;
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
foreach ( $setup_info as $appname => & $appdata )
{
// check if app is NOT installed
2021-08-03 18:53:05 +02:00
if ( ! ( $registered = $GLOBALS [ 'egw_setup' ] -> app_registered ( $appname )))
2002-03-03 22:47:30 +01:00
{
2021-08-03 18:53:05 +02:00
// check if app wants to be automatically installed on update to version x or always (unless uninstalled prior)
if ( isset ( $appdata [ 'autoinstall' ]) && ( $appdata [ 'autoinstall' ] === true && $registered !== null ||
2009-05-28 13:33:30 +02:00
$appdata [ 'autoinstall' ] === $this -> api_version_target ))
2002-03-03 22:47:30 +01:00
{
2016-04-02 21:55:08 +02:00
$info_c = $this -> current ( array ( $appname => $appdata ), $DEBUG );
$info = $this -> default_records ( $info_c , $DEBUG );
2009-05-28 13:33:30 +02:00
$appdata = $info [ $appname ];
2002-03-03 22:47:30 +01:00
continue ;
}
2009-05-28 13:33:30 +02:00
/* Don't try to upgrade an app that is not installed */
2008-10-21 16:22:27 +02:00
if ( $DEBUG )
{
2009-05-28 13:33:30 +02:00
echo " <p>process->upgrade(): Application not installed: $appname </p> \n " ;
2004-10-23 17:00:44 +02:00
}
2009-05-28 13:33:30 +02:00
unset ( $setup_info [ $appname ]);
continue ;
}
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
/* if upgrade required, or if we are running again after an upgrade or dependency failure */
if ( $DEBUG )
{
echo '<div style="text-align: left; border: thin dashed black; margin-top: 5px;">' . " process->upgrade(): Incoming : appname: $appname , version: $appdata[currentver] , status: $appdata[status] \n " ;
}
if ( $appdata [ 'status' ] == 'U' || $appdata [ 'status' ] == 'D' || $appdata [ 'status' ] == 'V' || $appdata [ 'status' ] == '' ) // TODO this is not getting set for api upgrade, sometimes ???
{
$currentver = $appdata [ 'currentver' ];
$targetver = $appdata [ 'version' ]; // The version we need to match when done
2016-05-03 00:26:40 +02:00
$appdir = EGW_SERVER_ROOT . '/' . $appname . '/setup/' ;
2009-05-28 13:33:30 +02:00
if ( file_exists ( $appdir . 'tables_update.inc.php' ))
{
if ( !@ $this -> updateincluded [ $appname ])
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
include ( $appdir . 'tables_update.inc.php' );
$this -> updateincluded [ $appname ] = True ;
}
while ( $currentver && $currentver != $targetver &&
function_exists ( $function = $appname . '_upgrade' . str_replace ( '.' , '_' , $currentver )))
{
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo " <br>process->upgrade(): $appname ( $currentver --> $targetver ): running $function () \n " ;
2004-10-23 17:00:44 +02:00
}
2009-05-28 13:33:30 +02:00
if ( ! ( $currentver = $function ()))
2008-10-21 16:22:27 +02:00
{
2004-10-23 17:00:44 +02:00
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo " <b>failed!!!</b> \n " ;
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
$appstatus = 'F' ;
2004-10-23 17:00:44 +02:00
}
2009-05-28 13:33:30 +02:00
else
2004-10-23 17:00:44 +02:00
{
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo " --> $currentver\n " ;
2002-03-03 22:47:30 +01:00
}
}
}
2009-05-28 13:33:30 +02:00
if ( $currentver == $targetver ) // upgrades succesful
2002-03-03 22:47:30 +01:00
{
2004-10-23 17:00:44 +02:00
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo " <br>process->upgrade(): Upgrade of $appname to $targetver is completed. \n " ;
2004-10-23 17:00:44 +02:00
}
2009-05-28 13:33:30 +02:00
$appstatus = 'C' ;
2004-10-23 17:00:44 +02:00
}
2009-05-28 13:33:30 +02:00
elseif ( $currentver )
2004-10-23 17:00:44 +02:00
{
2009-05-28 13:33:30 +02:00
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo " <br><b>process->upgrade(): No table upgrade available for appname: $appname , version: $currentver </b> \n " ;
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
$appdate [ 'currentver' ] = $targetver ;
$appstatus = 'F' ;
2002-03-03 22:47:30 +01:00
}
}
else
{
2002-03-04 08:18:46 +01:00
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo " <br>process->upgrade(): No table upgrade required/availible for $appname\n " ;
2002-03-03 22:47:30 +01:00
}
2004-10-23 17:00:44 +02:00
$appstatus = 'C' ;
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
if ( $appstatus == 'C' ) // update successful completed
{
$appdata [ 'currentver' ] = $targetver ;
if ( $GLOBALS [ 'egw_setup' ] -> app_registered ( $appname ))
{
$GLOBALS [ 'egw_setup' ] -> update_app ( $appname );
}
else
{
$GLOBALS [ 'egw_setup' ] -> register_app ( $appname );
}
}
}
else
{
2002-03-04 08:18:46 +01:00
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo " <br>process->upgrade(): No upgrade required for $appname\n " ;
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
$appstatus = 'C' ;
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
/* Done with this app, update status */
if ( $DEBUG )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
echo " <br>process->upgrade(): Outgoing : appname: $appname , status: $appstatus </div> \n " ;
2002-03-03 22:47:30 +01:00
}
2009-05-28 13:33:30 +02:00
$appdate [ 'status' ] = $appstatus ;
2002-03-03 22:47:30 +01:00
}
2016-04-02 21:55:08 +02:00
// update hooks
Api\Hooks :: read ( true );
2009-05-28 13:33:30 +02:00
/* Done, return current status */
return $setup_info ;
}
/**
* commit above processing to the db
*
*/
function post_process ( $tables , $DEBUG = False )
{
if ( ! $tables )
2002-03-03 22:47:30 +01:00
{
2009-05-28 13:33:30 +02:00
return False ;
}
2021-12-04 08:55:10 +01:00
return $this -> oProc -> ExecuteScripts ( $tables , $DEBUG );
2009-05-28 13:33:30 +02:00
}
2002-03-03 22:47:30 +01:00
2009-05-28 13:33:30 +02:00
/**
* send this a table name , returns printable column spec and keys for the table from schema_proc
*
* @ param $tablename table whose array you want to see
*/
function sql_to_array ( $tablename = '' )
{
if ( ! $tablename )
{
return False ;
}
2002-03-03 22:47:30 +01:00
2021-12-04 08:55:10 +01:00
if ( ! $this -> oProc )
2009-05-28 13:33:30 +02:00
{
$this -> init_process ();
}
2002-03-03 22:47:30 +01:00
2016-04-02 21:55:08 +02:00
$sColumns = null ;
2021-12-04 08:55:10 +01:00
$this -> oProc -> m_oTranslator -> _GetColumns ( $this -> oProc , $tablename , $sColumns );
2002-03-03 22:47:30 +01:00
2021-12-04 08:55:10 +01:00
foreach ( $this -> oProc -> m_oTranslator -> sCol as $tbldata )
2009-05-28 13:33:30 +02:00
{
$arr .= $tbldata ;
2002-03-03 22:47:30 +01:00
}
2021-12-04 08:55:10 +01:00
$pk = $this -> oProc -> m_oTranslator -> pk ;
$fk = $this -> oProc -> m_oTranslator -> fk ;
$ix = $this -> oProc -> m_oTranslator -> ix ;
$uc = $this -> oProc -> m_oTranslator -> uc ;
2009-05-28 13:33:30 +02:00
return array ( $arr , $pk , $fk , $ix , $uc );
2002-03-03 22:47:30 +01:00
}
2019-08-15 10:31:43 +02:00
/**
* Deinstall given apps
*
* @ param array $apps name of apps to deinstall
* @ param array $setup_info
* @ param bool $DEBUG = false
* @ return int
*/
function remove ( array $apps , array $setup_info , $DEBUG = false )
{
$historylog = new Api\Storage\History ();
2021-12-04 08:55:10 +01:00
$historylog -> db = $this -> db = $GLOBALS [ 'egw_setup' ] -> db ;
2019-08-15 10:31:43 +02:00
foreach ( $apps as $appname )
{
$app_title = $setup_info [ $appname ][ 'title' ] ? $setup_info [ $appname ][ 'title' ] : $setup_info [ $appname ][ 'name' ];
$terror = array ();
$terror [ $appname ] = $setup_info [ $appname ];
if ( $setup_info [ $appname ][ 'tables' ])
{
$this -> droptables ( $terror , $DEBUG );
echo '<br />' . $app_title . ' ' . lang ( 'tables dropped' ) . '.' ;
}
$GLOBALS [ 'egw_setup' ] -> deregister_app ( $setup_info [ $appname ][ 'name' ]);
echo '<br />' . $app_title . ' ' . lang ( 'deregistered' ) . '.' ;
$historylog -> appname = $appname ;
if ( $historylog -> delete ( null ))
{
echo '<br />' . $app_title . ' ' . lang ( 'Historylog removed' ) . '.' ;
}
// delete all application categories and ACL
2021-12-04 08:55:10 +01:00
$this -> db -> delete ( $GLOBALS [ 'egw_setup' ] -> cats_table , array ( 'cat_appname' => $appname ), __LINE__ , __FILE__ );
$this -> db -> delete ( $GLOBALS [ 'egw_setup' ] -> acl_table , array ( 'acl_appname' => $appname ), __LINE__ , __FILE__ );
2019-08-15 10:31:43 +02:00
}
return count ( $apps );
}
2022-04-01 13:38:18 +02:00
}