diff --git a/api/src/Egw/Applications.php b/api/src/Egw/Applications.php index 8e3cf96bf4..d789ebd99a 100755 --- a/api/src/Egw/Applications.php +++ b/api/src/Egw/Applications.php @@ -71,15 +71,18 @@ class Applications } /** - * populate array with a list of installed apps + * Populate array with a list of installed apps * + * egw_applications.app_enabled = -1 is NOT installed, but an uninstalled autoinstall app! + * + * @return array[] */ function read_installed_apps() { $GLOBALS['egw_info']['apps'] = Api\Cache::getInstance(__CLASS__, 'apps', function() { $apps = array(); - foreach($this->db->select($this->table_name,'*',false,__LINE__,__FILE__,false,'ORDER BY app_order ASC') as $row) + foreach($this->db->select($this->table_name,'*', ['app_enabled != -1'],__LINE__,__FILE__,false,'ORDER BY app_order ASC') as $row) { $apps[$row['app_name']] = Array( 'title' => $row['app_name'], diff --git a/setup/applications.php b/setup/applications.php index 634dae54e2..954cc53ce8 100644 --- a/setup/applications.php +++ b/setup/applications.php @@ -226,6 +226,9 @@ if (!empty($detail = $_GET['detail'])) { switch($key) { + case 'autoinstall': + $val = json_encode($val); + break; case 'title': continue 2; case 'tables': diff --git a/setup/inc/class.setup.inc.php b/setup/inc/class.setup.inc.php index e31c85c1ff..0fbe3d8413 100644 --- a/setup/inc/class.setup.inc.php +++ b/setup/inc/class.setup.inc.php @@ -516,16 +516,17 @@ class setup ),False,__LINE__,__FILE__); } try { - $this->db->insert($this->applications_table,array( - 'app_name' => $appname, - 'app_enabled' => $enable, - 'app_order' => $setup_info[$appname]['app_order'], - 'app_tables' => (string)$tables, // app_tables is NOT NULL - 'app_version' => $setup_info[$appname]['version'], - 'app_index' => $setup_info[$appname]['index'], - 'app_icon' => $setup_info[$appname]['icon'], - 'app_icon_app' => $setup_info[$appname]['icon_app'], - ),False,__LINE__,__FILE__); + $this->db->insert($this->applications_table, [ + 'app_enabled' => $enable, + 'app_order' => $setup_info[$appname]['app_order'], + 'app_tables' => (string)$tables, // app_tables is NOT NULL + 'app_version' => $setup_info[$appname]['version'], + 'app_index' => $setup_info[$appname]['index'], + 'app_icon' => $setup_info[$appname]['icon'], + 'app_icon_app' => $setup_info[$appname]['icon_app'], + ], [ + 'app_name' => $appname, + ], __LINE__, __FILE__); } catch (Api\Db\Exception\InvalidSql $e) { @@ -548,7 +549,7 @@ class setup * Check if an application has info in the db * * @param $appname Application 'name' with a matching $setup_info[$appname] array slice - * @param $enabled optional, set to False to not enable this app + * @return boolean|null null: autoinstalled app which got uninstalled */ function app_registered($appname) { @@ -563,13 +564,13 @@ class setup // _debug_array($setup_info[$appname]); } - if ($this->db->select($this->applications_table,'COUNT(*)',array('app_name' => $appname),__LINE__,__FILE__)->fetchColumn()) + if (($enabled = $this->db->select($this->applications_table, 'app_enabled', ['app_name' => $appname], __LINE__,__FILE__)->fetchColumn()) !== false) { if(@$GLOBALS['DEBUG']) { echo '... app previously registered.'; } - return True; + return $enabled <= -1 ? null : true; } if(@$GLOBALS['DEBUG']) { @@ -676,10 +677,35 @@ class setup $this->db->delete(Api\Config::TABLE, array('config_app'=>$appname),__LINE__,__FILE__); } //echo 'DELETING application: ' . $appname; - $this->db->delete($this->applications_table,array('app_name'=>$appname),__LINE__,__FILE__); + + // when uninstalling an autoinstall app, we must mark it deleted in the DB, otherwise it will install again the next update + if (file_exists($file = EGW_SERVER_ROOT.'/'.$appname.'/setup/setup.inc.php')) + { + $setup_info = []; + include($file); + } + if (!empty($setup_info[$appname]['autoinstall']) && $setup_info[$appname]['autoinstall'] === true) + { + $this->db->update($this->applications_table, [ + 'app_enabled' => -1, + 'app_tables' => '', + 'app_version' => 'uninstalled', + 'app_index' => null, + ], [ + 'app_name' => $appname, + ], __LINE__, __FILE__); + } + else + { + $this->db->delete($this->applications_table, ['app_name' => $appname], __LINE__, __FILE__); + } Api\Egw\Applications::invalidate(); + // unregister hooks, before removing links + unset($GLOBALS['egw_info']['apps'][$appname]); + Api\Hooks::read(true); + // Remove links to the app Link::unlink(0, $appname); } @@ -1219,6 +1245,8 @@ class setup { static $table_names = False; + if(!is_object($this->db)) $this->loaddb(); + if (!$table_names || $force_refresh) $table_names = $this->db->table_names(); if (!$table_names) return false; diff --git a/setup/inc/class.setup_detection.inc.php b/setup/inc/class.setup_detection.inc.php index 2132310211..cda523d231 100755 --- a/setup/inc/class.setup_detection.inc.php +++ b/setup/inc/class.setup_detection.inc.php @@ -62,7 +62,7 @@ class setup_detection /* one of these tables exists. checking for post/pre beta version */ if($GLOBALS['egw_setup']->applications_table != 'applications') { - foreach($GLOBALS['egw_setup']->db->select($GLOBALS['egw_setup']->applications_table,'*',false,__LINE__,__FILE__) as $row) + foreach($GLOBALS['egw_setup']->db->select($GLOBALS['egw_setup']->applications_table, '*', 'app_enabled != -1', __LINE__, __FILE__) as $row) { $app = $row['app_name']; if (!isset($setup_info[$app])) // app source no longer there diff --git a/setup/inc/class.setup_process.inc.php b/setup/inc/class.setup_process.inc.php index 3377e847c0..74988baa9b 100755 --- a/setup/inc/class.setup_process.inc.php +++ b/setup/inc/class.setup_process.inc.php @@ -618,10 +618,10 @@ class setup_process foreach($setup_info as $appname => &$appdata) { // check if app is NOT installed - if(!$GLOBALS['egw_setup']->app_registered($appname)) + if (!($registered = $GLOBALS['egw_setup']->app_registered($appname))) { - // check if app wants to be automatically installed on update to version x or allways - if (isset($appdata['autoinstall']) && ($appdata['autoinstall'] === true || + // 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 || $appdata['autoinstall'] === $this->api_version_target)) { $info_c = $this->current(array($appname => $appdata), $DEBUG);