diff --git a/public/legacy/install/perform_setup_service.php b/public/legacy/install/perform_setup_service.php
new file mode 100644
index 000000000..05d2ead96
--- /dev/null
+++ b/public/legacy/install/perform_setup_service.php
@@ -0,0 +1,743 @@
+')
+{
+ $fname = 'install/status.json';
+ if (!$overwrite && file_exists($fname)) {
+ $stat = json_decode(file_get_contents($fname), null, 512, JSON_THROW_ON_ERROR);
+ //$msg = json_encode($stat);
+ $msg = $stat->message . $before . $msg;
+ }
+ file_put_contents(
+ $fname, json_encode(
+ array(
+ 'message' => $msg,
+ 'command' => $cmd,
+ ), JSON_THROW_ON_ERROR
+ )
+ );
+}
+
+installStatus($mod_strings['LBL_START'], null, true, '');
+
+// This file will load the configuration settings from session data,
+// write to the config file, and execute any necessary database steps.
+$GLOBALS['installing'] = true;
+if (!isset($install_script) || !$install_script) {
+ $performSetupResult = [
+ 'success' => false,
+ 'messages' => ['Install error: Unable to process script directly. ']
+ ];
+ return;
+}
+ini_set("output_buffering", "0");
+set_time_limit(3600);
+// flush after each output so the user can see the progress in real-time
+ob_implicit_flush();
+
+
+require_once('install/install_utils.php');
+
+require_once('modules/TableDictionary.php');
+
+global $trackerManager;
+
+$trackerManager = TrackerManager::getInstance();
+$trackerManager->pause();
+
+global $cache_dir;
+global $line_entry_format;
+global $line_exit_format;
+global $rel_dictionary;
+global $render_table_close;
+global $render_table_open;
+global $setup_db_admin_password;
+global $setup_db_admin_user_name;
+global $setup_db_create_database;
+global $setup_db_create_sugarsales_user;
+global $setup_db_database_name;
+global $setup_db_drop_tables;
+global $setup_db_host_instance;
+global $setup_db_port_num;
+global $setup_db_host_name;
+global $demoData;
+global $setup_db_sugarsales_password;
+global $setup_db_sugarsales_user;
+global $setup_site_admin_user_name;
+global $setup_site_admin_password;
+global $setup_site_guid;
+global $setup_site_url;
+global $parsed_url;
+global $setup_site_host_name;
+global $setup_site_log_dir;
+global $setup_site_log_file;
+global $setup_site_session_path;
+global $setup_site_log_level;
+
+
+$cache_dir = sugar_cached("");
+$line_entry_format = "     ";
+$line_exit_format = "...   ";
+$rel_dictionary = $dictionary; // sourced by modules/TableDictionary.php
+$render_table_close = "";
+$render_table_open = "";
+$setup_db_admin_password = $_SESSION['setup_db_admin_password'];
+$setup_db_admin_user_name = $_SESSION['setup_db_admin_user_name'];
+$setup_db_create_database = $_SESSION['setup_db_create_database'];
+$setup_db_create_sugarsales_user = $_SESSION['setup_db_create_sugarsales_user'];
+$setup_db_database_name = $_SESSION['setup_db_database_name'];
+$setup_db_drop_tables = $_SESSION['setup_db_drop_tables'];
+$setup_db_host_instance = $_SESSION['setup_db_host_instance'];
+$setup_db_port_num = $_SESSION['setup_db_port_num'];
+$setup_db_host_name = $_SESSION['setup_db_host_name'];
+$demoData = $_SESSION['demoData'];
+$setup_db_sugarsales_password = $_SESSION['setup_db_sugarsales_password'];
+$setup_db_sugarsales_user = $_SESSION['setup_db_sugarsales_user'];
+$setup_site_admin_user_name = $_SESSION['setup_site_admin_user_name'];
+$setup_site_admin_password = $_SESSION['setup_site_admin_password'];
+$setup_site_guid = (isset($_SESSION['setup_site_specify_guid']) && $_SESSION['setup_site_specify_guid'] != '') ? $_SESSION['setup_site_guid'] : '';
+$setup_site_url = $_SESSION['setup_site_url'];
+$parsed_url = parse_url((string)$setup_site_url);
+$setup_site_host_name = $parsed_url['host'];
+$setup_site_log_dir = isset($_SESSION['setup_site_custom_log_dir']) ? $_SESSION['setup_site_log_dir'] : '.';
+$setup_site_log_file = 'suitecrm.log'; // may be an option later
+$setup_site_session_path = isset($_SESSION['setup_site_custom_session_path']) ? $_SESSION['setup_site_session_path'] : '';
+$setup_site_log_level = 'fatal';
+
+$langHeader = get_language_header();
+
+$install_db_setup_messages = [];
+
+installStatus($mod_strings['STAT_CONFIGURATION'], null, false, '');
+installLog("calling handleSugarConfig()");
+$bottle = handleSugarConfig();
+//installLog("calling handleLog4Php()");
+//handleLog4Php();
+
+$server_software = $_SERVER["SERVER_SOFTWARE"];
+if (strpos((string)$server_software, 'Microsoft-IIS') !== false) {
+ installLog("calling handleWebConfig()");
+ handleWebConfig();
+} else {
+ installLog("calling handleHtaccess()");
+ handleHtaccess();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//// START TABLE STUFF
+
+$install_db_setup_messages[] = $mod_strings['LBL_PERFORM_TABLES'];
+
+// create the SugarCRM database
+if ($setup_db_create_database) {
+ installLog("calling handleDbCreateDatabase()");
+ installerHook('pre_handleDbCreateDatabase');
+ handleDbCreateDatabase();
+ installerHook('post_handleDbCreateDatabase');
+} else {
+
+// ensure the charset and collation are utf8
+ installLog("calling handleDbCharsetCollation()");
+ installerHook('pre_handleDbCharsetCollation');
+ handleDbCharsetCollation();
+ installerHook('post_handleDbCharsetCollation');
+}
+
+// create the SugarCRM database user
+if ($setup_db_create_sugarsales_user) {
+ installerHook('pre_handleDbCreateSugarUser');
+ handleDbCreateSugarUser();
+ installerHook('post_handleDbCreateSugarUser');
+}
+
+foreach ($beanFiles as $bean => $file) {
+ require_once($file);
+}
+// load up the config_override.php file.
+// This is used to provide default user settings
+if (is_file("config_override.php")) {
+ require_once("config_override.php");
+}
+
+global $db;
+global $startTime;
+global $focus;
+global $processed_tables;
+global $db;
+global $empty;
+global $new_tables;
+global $new_config;
+global $new_report;
+global $nonStandardModules;
+
+
+$db = DBManagerFactory::getInstance();
+$startTime = microtime(true);
+$focus = 0;
+$processed_tables = array(); // for keeping track of the tables we have worked on
+$empty = array();
+$new_tables = 1; // is there ever a scenario where we DON'T create the admin user?
+$new_config = 1;
+$new_report = 1;
+
+// add non-module Beans to this array to keep the installer from erroring.
+$nonStandardModules = array(//'Tracker',
+);
+
+
+/**
+ * loop through all the Beans and create their tables
+ */
+installStatus($mod_strings['STAT_CREATE_DB']);
+installLog("looping through all the Beans and create their tables");
+//start by clearing out the vardefs
+VardefManager::clearVardef();
+installerHook('pre_createAllModuleTables');
+
+
+foreach ($beanFiles as $bean => $file) {
+ $doNotInit = array('Scheduler', 'SchedulersJob', 'ProjectTask', 'jjwg_Maps', 'jjwg_Address_Cache', 'jjwg_Areas', 'jjwg_Markers');
+
+ if (in_array($bean, $doNotInit)) {
+ $focus = new $bean(false);
+ } else {
+ $focus = new $bean();
+ }
+
+ if ($bean == 'Configurator') {
+ continue;
+ }
+
+ $table_name = $focus->table_name;
+ //installStatus(sprintf($mod_strings['STAT_CREATE_DB_TABLE'], $focus->table_name ));
+ installLog("processing table " . $focus->table_name);
+ // check to see if we have already setup this table
+ if (!in_array($table_name, $processed_tables)) {
+ if (!file_exists("modules/" . $focus->module_dir . "/vardefs.php")) {
+ continue;
+ }
+ if (!in_array($bean, $nonStandardModules)) {
+ require_once("modules/" . $focus->module_dir . "/vardefs.php"); // load up $dictionary
+ if (isset($dictionary[$focus->object_name]['table']) && $dictionary[$focus->object_name]['table'] == 'does_not_exist') {
+ continue; // support new vardef definitions
+ }
+ } else {
+ continue; //no further processing needed for ignored beans.
+ }
+
+ // table has not been setup...we will do it now and remember that
+ $processed_tables[] = $table_name;
+
+ $focus->db->database = $db->database; // set db connection so we do not need to reconnect
+
+ if ($setup_db_drop_tables) {
+ drop_table_install($focus);
+ installLog("dropping table " . $focus->table_name);
+ }
+
+ if (create_table_if_not_exist($focus)) {
+ installLog("creating table " . $focus->table_name);
+ if ($bean == "User") {
+ $new_tables = 1;
+ }
+ if ($bean == "Administration") {
+ $new_config = 1;
+ }
+ }
+
+ installLog("creating Relationship Meta for " . $focus->getObjectName());
+ installerHook('pre_createModuleTable', array('module' => $focus->getObjectName()));
+ SugarBean::createRelationshipMeta($focus->getObjectName(), $db, $table_name, $empty, $focus->module_dir);
+ installerHook('post_createModuleTable', array('module' => $focus->getObjectName()));
+ } // end if()
+}
+
+
+installerHook('post_createAllModuleTables');
+
+//// END TABLE STUFF
+
+///////////////////////////////////////////////////////////////////////////////
+//// START RELATIONSHIP CREATION
+
+ksort($rel_dictionary);
+foreach ($rel_dictionary as $rel_name => $rel_data) {
+ $table = $rel_data['table'];
+
+ if ($setup_db_drop_tables) {
+ if ($db->tableExists($table)) {
+ $db->dropTableName($table);
+ }
+ }
+
+ if (!$db->tableExists($table)) {
+ $db->createTableParams($table, $rel_data['fields'], $rel_data['indices']);
+ }
+
+ SugarBean::createRelationshipMeta($rel_name, $db, $table, $rel_dictionary, '');
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//// START CREATE DEFAULTS
+$install_db_setup_messages[] = $mod_strings['LBL_PERFORM_CREATE_DEFAULT'];
+
+installStatus($mod_strings['STAT_CREATE_DEFAULT_SETTINGS']);
+installLog("Begin creating Defaults");
+installerHook('pre_createDefaultSettings');
+if ($new_config) {
+ installLog("insert defaults into config table");
+ insert_default_settings();
+}
+installerHook('post_createDefaultSettings');
+
+
+installerHook('pre_createUsers');
+if ($new_tables) {
+ $install_db_setup_messages[] = $mod_strings['LBL_PERFORM_DEFAULT_USERS'];
+ installLog($mod_strings['LBL_PERFORM_DEFAULT_USERS']);
+ create_default_users();
+ $install_db_setup_messages[] = $mod_strings['LBL_PERFORM_DEFAULT_DONE'];
+} else {
+ $install_db_setup_messages[] = $mod_strings['LBL_PERFORM_ADMIN_PASSWORD'];
+ installLog($mod_strings['LBL_PERFORM_ADMIN_PASSWORD']);
+ $db->setUserName($setup_db_sugarsales_user);
+ $db->setUserPassword($setup_db_sugarsales_password);
+ set_admin_password($setup_site_admin_password);
+ $install_db_setup_messages[] = $mod_strings['LBL_PERFORM_DONE'];
+}
+installerHook('post_createUsers');
+
+
+// default OOB schedulers
+
+$install_db_setup_messages[] = $mod_strings['LBL_PERFORM_DEFAULT_SCHEDULER'];
+installLog($mod_strings['LBL_PERFORM_DEFAULT_SCHEDULER']);
+$scheduler = BeanFactory::newBean('Schedulers');
+installerHook('pre_createDefaultSchedulers');
+$scheduler->rebuildDefaultSchedulers();
+installerHook('post_createDefaultSchedulers');
+$install_db_setup_messages[] = $mod_strings['LBL_PERFORM_DONE'];
+
+
+// Enable Sugar Feeds and add all feeds by default
+installLog("Enable SugarFeeds");
+enableSugarFeeds();
+
+// Install the logic hook for WorkFLow
+installLog("Creating WorkFlow logic hook");
+if (!function_exists('createWorkFlowLogicHook')) {
+ function createWorkFlowLogicHook($filePath = 'Extension/application/Ext/LogicHooks/AOW_WorkFlow_Hook.php')
+ {
+ $customFileLoc = create_custom_directory($filePath);
+ $fp = sugar_fopen($customFileLoc, 'wb');
+ $contents = <<