/** * uninstall app * * @param Tinebase_Model_Application $_application */ protected function _uninstallApplication(Tinebase_Model_Application $_application) { Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Uninstall ' . $_application); $applicationTables = Tinebase_Application::getInstance()->getApplicationTables($_application); do { $oldCount = count($applicationTables); if ($_application->name == 'Tinebase') { $installedApplications = Tinebase_Application::getInstance()->getApplications(NULL, 'id'); if (count($installedApplications) !== 1) { throw new Setup_Exception_Dependency('Failed to uninstall application "Tinebase" because of dependencies to other installed applications.'); } } foreach ($applicationTables as $key => $table) { Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Remove table: {$table}"); try { $this->_backend->dropTable($table); if ($_application->name != 'Tinebase') { Tinebase_Application::getInstance()->removeApplicationTable($_application, $table); } unset($applicationTables[$key]); } catch (Zend_Db_Statement_Exception $e) { // we need to catch exceptions here, as we don't want to break here, as a table // might still have some foreign keys $message = $e->getMessage(); Setup_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " Could not drop table {$table} - " . $message); // remove app table if table not found in db if (preg_match('/SQLSTATE\\[42S02\\]: Base table or view not found/', $message) && $_application->name != 'Tinebase') { Tinebase_Application::getInstance()->removeApplicationTable($_application, $table); unset($applicationTables[$key]); } } } if ($oldCount > 0 && count($applicationTables) == $oldCount) { throw new Setup_Exception('dead lock detected oldCount: ' . $oldCount); } } while (count($applicationTables) > 0); if ($_application->name != 'Tinebase') { // delete containers, config options and other data for app Tinebase_Application::getInstance()->removeApplicationData($_application); // remove application from table of installed applications Tinebase_Application::getInstance()->deleteApplication($_application); } Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Removed app: " . $_application->name); }
/** * uninstall app * * @param Tinebase_Model_Application $_application * @throws Setup_Exception */ protected function _uninstallApplication(Tinebase_Model_Application $_application, $uninstallAll = false) { if ($this->_backend === null) { throw new Setup_Exception('No setup backend available'); } Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Uninstall ' . $_application); try { $applicationTables = Tinebase_Application::getInstance()->getApplicationTables($_application); } catch (Zend_Db_Statement_Exception $zdse) { Setup_Core::getLogger()->err(__METHOD__ . '::' . __LINE__ . " " . $zdse); throw new Setup_Exception('Could not uninstall ' . $_application . ' (you might need to remove the tables by yourself): ' . $zdse->getMessage()); } $disabledFK = FALSE; $db = Tinebase_Core::getDb(); do { $oldCount = count($applicationTables); if ($_application->name == 'Tinebase') { $installedApplications = Tinebase_Application::getInstance()->getApplications(NULL, 'id'); if (count($installedApplications) !== 1) { throw new Setup_Exception_Dependency('Failed to uninstall application "Tinebase" because of dependencies to other installed applications.'); } } foreach ($applicationTables as $key => $table) { Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Remove table: {$table}"); try { // drop foreign keys which point to current table first $foreignKeys = $this->_backend->getExistingForeignKeys($table); foreach ($foreignKeys as $foreignKey) { Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Drop index: " . $foreignKey['table_name'] . ' => ' . $foreignKey['constraint_name']); $this->_backend->dropForeignKey($foreignKey['table_name'], $foreignKey['constraint_name']); } // drop table $this->_backend->dropTable($table); if ($_application->name != 'Tinebase') { Tinebase_Application::getInstance()->removeApplicationTable($_application, $table); } unset($applicationTables[$key]); } catch (Zend_Db_Statement_Exception $e) { // we need to catch exceptions here, as we don't want to break here, as a table // might still have some foreign keys // this works with mysql only $message = $e->getMessage(); Setup_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " Could not drop table {$table} - " . $message); // remove app table if table not found in db if (preg_match('/SQLSTATE\\[42S02\\]: Base table or view not found/', $message) && $_application->name != 'Tinebase') { Tinebase_Application::getInstance()->removeApplicationTable($_application, $table); unset($applicationTables[$key]); } else { Setup_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . " Disabling foreign key checks ... "); if ($db instanceof Zend_Db_Adapter_Pdo_Mysql) { $db->query("SET FOREIGN_KEY_CHECKS=0"); } $disabledFK = TRUE; } } } if ($oldCount > 0 && count($applicationTables) == $oldCount) { throw new Setup_Exception('dead lock detected oldCount: ' . $oldCount); } } while (count($applicationTables) > 0); if ($disabledFK) { if ($db instanceof Zend_Db_Adapter_Pdo_Mysql) { Setup_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . " Enabling foreign key checks again... "); $db->query("SET FOREIGN_KEY_CHECKS=1"); } } if ($_application->name != 'Tinebase') { if (!$uninstallAll) { Tinebase_Relations::getInstance()->removeApplication($_application->name); Tinebase_Timemachine_ModificationLog::getInstance()->removeApplication($_application); // delete containers, config options and other data for app Tinebase_Application::getInstance()->removeApplicationData($_application); } // remove application from table of installed applications Tinebase_Application::getInstance()->deleteApplication($_application); } Setup_Uninitialize::uninitialize($_application); Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Removed app: " . $_application->name); }