Ejemplo n.º 1
0
 public function run()
 {
     // somehow we missed quick create configuration on upgrade. here we update it too.
     if (version_compare($this->from_version, '7.6', '<') && is_file('custom/include/DashletContainer/Containers/DCActions.php')) {
         require_once 'modules/Administration/views/view.configureshortcutbar.php';
         $quickCreate = new ViewConfigureshortcutbar();
         $modules = $quickCreate->getQuickCreateModules();
         $needToUpdate = true;
         foreach (array_merge($modules['enabled'], $modules['disabled']) as $module => $definition) {
             // it means that someone already configured that so we don't need to do anything.
             if (is_file("custom/modules/{$module}/clients/base/menus/quickcreate/quickcreate.php")) {
                 $needToUpdate = false;
                 break;
             }
         }
         if ($needToUpdate) {
             $DCActions = array();
             require 'custom/include/DashletContainer/Containers/DCActions.php';
             $DCActions = array_flip($DCActions);
             $successful = $quickCreate->saveChangesToQuickCreateMetadata($modules['enabled'], $modules['disabled'], $DCActions);
             if ($successful) {
                 MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_MODULES));
             }
         }
     }
     // Only run when coming from a version lower than 7.2.
     if (version_compare($this->from_version, '7.2', '<')) {
         $this->fixQuickCreateOrder();
     }
     // Only run when coming from a version lower than 7.6.
     if (version_compare($this->from_version, '7.6', '<')) {
         $this->addStickyResizableColumnsFlag('recordlist');
         $this->addStickyResizableColumnsFlag('history-summary');
     }
 }
Ejemplo n.º 2
0
 /**
  * This function allows a user with Forecasts admin rights to reset the Forecasts settings so that the Forecasts wizard
  * dialog will appear once again.
  *
  */
 public function action_resetSettings()
 {
     global $current_user;
     if ($current_user->isAdminForModule('Forecasts')) {
         $db = DBManagerFactory::getInstance();
         $db->query("UPDATE config SET value = '0' WHERE category = 'Forecasts' and name in ('is_setup', 'has_commits')");
         MetaDataManager::refreshModulesCache(array('Forecasts'));
         MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_CONFIG));
         echo '<script>' . navigateToSidecar(buildSidecarRoute("Forecasts")) . ';</script>';
         exit;
     }
     $this->view = 'noaccess';
 }
 /**
  * Saves $data to the $name dropdown for the $role name
  *
  * @param $fieldName
  * @param $role
  * @param $data
  * @return boolean
  */
 public function handleSave($fieldName, $role, $data)
 {
     $path = $this->getFilePath($fieldName, $role);
     $dir = dirname($path);
     if (!SugarAutoLoader::ensureDir($dir)) {
         $GLOBALS['log']->error("ParserRoleDropDownFilter :: Cannot create directory {$dir}");
         return false;
     }
     $result = write_array_to_file("role_dropdown_filters['{$fieldName}']", $this->convertFormData($data), $path);
     if ($result) {
         $this->rebuildExtension($role);
         MetaDataManager::refreshSectionCache(MetaDataManager::MM_EDITDDFILTERS, array(), array('role' => $role));
     }
     return $result;
 }
 /**
  * @see SugarView::display()
  */
 public function display()
 {
     require_once "include/JSON.php";
     $json = new JSON();
     global $mod_strings;
     $title = getClassicModuleTitle("Administration", array("<a href='index.php?module=Administration&action=index'>{$mod_strings['LBL_MODULE_NAME']}</a>", translate('LBL_CONFIGURE_SHORTCUT_BAR')), false);
     $msg = "";
     $GLOBALS['log']->info("Administration ConfigureShortcutBar view");
     $quickCreateModules = $this->getQuickCreateModules();
     //If save is set, save then let the user know if the save worked.
     if (!empty($_REQUEST['enabled_modules'])) {
         $toDecode = html_entity_decode($_REQUEST['enabled_modules'], ENT_QUOTES);
         // get the enabled
         $enabledModules = array_flip(json_decode($toDecode));
         $successful = $this->saveChangesToQuickCreateMetadata($quickCreateModules['enabled'], $quickCreateModules['disabled'], $enabledModules);
         if ($successful) {
             MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_MODULES));
             echo "true";
         } else {
             echo translate("LBL_SAVE_FAILED");
         }
     } else {
         $enabled = $this->sortEnabledModules($quickCreateModules['enabled']);
         $enabled = $this->filterAndFormatModuleList($enabled);
         ksort($quickCreateModules['disabled']);
         $disabled = $this->filterAndFormatModuleList($quickCreateModules['disabled']);
         $this->ss->assign('APP', $GLOBALS['app_strings']);
         $this->ss->assign('MOD', $GLOBALS['mod_strings']);
         $this->ss->assign('title', $title);
         $this->ss->assign('enabled_modules', $json->encode($enabled));
         $this->ss->assign('disabled_modules', $json->encode($disabled));
         $this->ss->assign('description', translate("LBL_CONFIGURE_SHORTCUT_BAR"));
         $this->ss->assign('msg', $msg);
         $returnModule = !empty($_REQUEST['return_module']) ? $_REQUEST['return_module'] : 'Administration';
         $returnAction = !empty($_REQUEST['return_action']) ? $_REQUEST['return_action'] : 'index';
         $this->ss->assign('RETURN_MODULE', $returnModule);
         $this->ss->assign('RETURN_ACTION', $returnAction);
         echo $this->ss->fetch('modules/Administration/templates/ShortcutBar.tpl');
     }
 }
Ejemplo n.º 5
0
 /**
  * action_saveglobalsearchsettings
  *
  * This method handles saving the selected modules to display in the Global Search Settings.
  * It instantiates an instance of UnifiedSearchAdvanced and then calls the saveGlobalSearchSettings
  * method.
  *
  */
 public function action_saveglobalsearchsettings()
 {
     global $current_user, $app_strings;
     if (!is_admin($current_user)) {
         sugar_die($GLOBALS['app_strings']['ERR_NOT_ADMIN']);
     }
     try {
         require_once 'modules/Home/UnifiedSearchAdvanced.php';
         $unifiedSearchAdvanced = new UnifiedSearchAdvanced();
         $unifiedSearchAdvanced->saveGlobalSearchSettings();
         //Save FTS Settings
         $type = !empty($_REQUEST['type']) ? $_REQUEST['type'] : '';
         $host = !empty($_REQUEST['host']) ? $_REQUEST['host'] : '';
         $port = !empty($_REQUEST['port']) ? $_REQUEST['port'] : '';
         $ftsConfig = $this->mergeFtsConfig($type, array('port' => $port, 'host' => $host));
         $this->cfg = new Configurator();
         $this->cfg->config['full_text_engine'] = '';
         $this->cfg->saveConfig();
         $ftsConnectionValid = TRUE;
         if (!empty($type)) {
             //Check if the connection is valid on save:
             require_once 'include/SugarSearchEngine/SugarSearchEngineFactory.php';
             $searchEngine = SugarSearchEngineFactory::getInstance($type, $ftsConfig);
             $result = $searchEngine->getServerStatus();
             if (!$result['valid']) {
                 $ftsConnectionValid = FALSE;
             }
             // bug 54274 -- only bother with an override if we have data to place there, empty string breaks Sugar On-Demand!
             $ftsConfig['valid'] = $ftsConnectionValid;
             $this->cfg->config['full_text_engine'] = array($type => $ftsConfig);
             $this->cfg->handleOverride();
         }
         // Refresh the server info & module list sections of the metadata
         MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_SERVERINFO, MetaDataManager::MM_MODULES));
         if (!$ftsConnectionValid) {
             echo $GLOBALS['mod_strings']['LBL_FTS_CONNECTION_INVALID'];
         } else {
             echo "true";
         }
     } catch (Exception $ex) {
         echo "false";
     }
 }
Ejemplo n.º 6
0
 /**
  * Same as SugarBean::mark_deleted except clears api cache.
  * @param $id
  */
 public function mark_deleted($id)
 {
     sugar_cache_clear('currency_list');
     $return = parent::mark_deleted($id);
     // The per-module cache doesn't need to be cleared here
     MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_CURRENCIES));
 }
Ejemplo n.º 7
0
 public function action_SaveDropDown()
 {
     $parser = new ParserDropDown();
     $parser->saveDropDown($_REQUEST);
     MetaDataManager::refreshSectionCache(MetaDataManager::MM_LABELS);
     MetaDataManager::refreshSectionCache(MetaDataManager::MM_ORDEREDLABELS);
     MetaDataManager::refreshSectionCache(MetaDataManager::MM_EDITDDFILTERS);
     $this->view = 'dropdowns';
 }
Ejemplo n.º 8
0
 /**
  * Saves the company logo to the custom directory for the default theme, so all themes can use it
  *
  * @param string $path path to the image to set as the company logo image
  */
 function saveCompanyLogo($path)
 {
     $path = $this->checkTempImage($path);
     $logo = create_custom_directory(SugarThemeRegistry::current()->getDefaultImagePath() . '/company_logo.png');
     copy($path, $logo);
     SugarAutoLoader::addToMap($logo);
     sugar_cache_clear('company_logo_attributes');
     SugarThemeRegistry::clearAllCaches();
     SugarThemeRegistry::current()->clearImageCache('company_logo.png');
     MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_LOGOURL));
 }
Ejemplo n.º 9
0
 function build()
 {
     $modulesToBuild = array();
     if (!isset($this->relationships[$this->newRelationshipName])) {
         $GLOBALS['log']->fatal("Could not find a relationship by the name of {$this->newRelationshipName}, you will have to quick repair and rebuild to get the new relationship added.");
     } else {
         $newRel = $this->relationships[$this->newRelationshipName];
         $newRelDef = $newRel->getDefinition();
         $modulesToBuild[$newRelDef['rhs_module']] = true;
         $modulesToBuild[$newRelDef['lhs_module']] = true;
     }
     $basepath = "custom/Extension/modules";
     $this->activitiesToAdd = false;
     // and mark all as built so that the next time we come through we'll know and won't build again
     foreach ($this->relationships as $name => $relationship) {
         if ($relationship->readonly()) {
             continue;
         }
         $definition = $relationship->getDefinition();
         // activities will always appear on the rhs only - lhs will be always be this module in MB
         if (strtolower($definition['rhs_module']) == 'activities') {
             $this->activitiesToAdd = true;
             $relationshipName = $definition['relationship_name'];
             foreach (self::$activities as $activitiesSubModuleLower => $activitiesSubModuleName) {
                 $definition['rhs_module'] = $activitiesSubModuleName;
                 $definition['for_activities'] = true;
                 $definition['relationship_name'] = $relationshipName . '_' . $activitiesSubModuleLower;
                 $this->relationships[$definition['relationship_name']] = RelationshipFactory::newRelationship($definition);
             }
             unset($this->relationships[$name]);
         }
     }
     $GLOBALS['log']->info(get_class($this) . "->build(): installing relationships");
     $MBModStrings = $GLOBALS['mod_strings'];
     $adminModStrings = return_module_language('', 'Administration');
     // required by ModuleInstaller
     foreach ($this->relationships as $name => $relationship) {
         if ($relationship->readonly()) {
             continue;
         }
         $relationship->setFromStudio();
         $GLOBALS['mod_strings'] = $MBModStrings;
         $installDefs = parent::build($basepath, "<basepath>", array($name => $relationship));
         // and mark as built so that the next time we come through we'll know and won't build again
         $relationship->setReadonly();
         $this->relationships[$name] = $relationship;
         // now install the relationship - ModuleInstaller normally only does this as part of a package load where it installs the relationships defined in the manifest. However, we don't have a manifest or a package, so...
         // If we were to chose to just use the Extension mechanism, without using the ModuleInstaller install_...() methods, we must :
         // 1)   place the information for each side of the relationship in the appropriate Ext directory for the module, which means specific $this->save...() methods for DeployedRelationships, and
         // 2)   we must also manually add the relationship into the custom/application/Ext/TableDictionary/tabledictionary.ext.php file as install_relationship doesn't handle that (install_relationships which requires the manifest however does)
         //      Relationships must be in tabledictionary.ext.php for the Admin command Rebuild Relationships to reliably work:
         //      Rebuild Relationships looks for relationships in the modules vardefs.php, in custom/modules/<modulename>/Ext/vardefs/vardefs.ext.php, and in modules/TableDictionary.php and custom/application/Ext/TableDictionary/tabledictionary.ext.php
         //      if the relationship is not defined in one of those four places it could be deleted during a rebuilt, or during a module installation (when RebuildRelationships.php deletes all entries in the Relationships table)
         // So instead of doing this, we use common save...() methods between DeployedRelationships and UndeployedRelationships that will produce installDefs,
         // and rather than building a full manifest file to carry them, we manually add these installDefs to the ModuleInstaller, and then
         // individually call the appropriate ModuleInstaller->install_...() methods to take our relationship out of our staging area and expand it out to the individual module Ext areas
         $GLOBALS['mod_strings'] = $adminModStrings;
         require_once 'ModuleInstall/ModuleInstaller.php';
         $mi = new ModuleInstaller();
         $mi->id_name = 'custom' . $name;
         // provide the moduleinstaller with a unique name for this relationship - normally this value is set to the package key...
         $mi->installdefs = $installDefs;
         $mi->base_dir = $basepath;
         $mi->silent = true;
         VardefManager::clearVardef();
         $mi->install_relationships();
         $mi->install_languages();
         $mi->install_vardefs();
         $mi->install_layoutdefs();
         $mi->install_extensions();
         $mi->install_client_files();
     }
     $GLOBALS['mod_strings'] = $MBModStrings;
     // finally, restore the ModuleBuilder mod_strings
     // Anything that runs in-process needs to reload their vardefs
     $GLOBALS['reload_vardefs'] = true;
     // save out the updated definitions so that we keep track of the change in built status
     // sending false so we don't rebuild relationshsips for a third time.
     $this->save(false);
     $mi = new ModuleInstaller();
     $mi->silent = true;
     $mi->rebuild_relationships($modulesToBuild);
     // now clear all caches so that our changes are visible
     require_once 'modules/Administration/QuickRepairAndRebuild.php';
     $rac = new RepairAndClear();
     $rac->module_list = $modulesToBuild;
     $rac->clearJsFiles();
     $rac->clearVardefs();
     $rac->clearJsLangFiles();
     $rac->clearLanguageCache();
     $rac->rebuildExtensions(array_keys($modulesToBuild));
     $rac->clearVardefs();
     foreach ($rac->module_list as $moduleName => $ignore) {
         // Now rebuild the vardefs in memory
         $bean = BeanFactory::newBean($moduleName);
         VardefManager::loadVardef($bean->module_dir, $bean->object_name, true, array('bean' => $bean));
     }
     foreach (array_keys($modulesToBuild) as $module) {
         unset($GLOBALS['dictionary'][BeanFactory::getObjectName($module)]);
     }
     SugarRelationshipFactory::rebuildCache();
     MetaDataManager::refreshLanguagesCache(array($GLOBALS['current_language']));
     MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_RELATIONSHIPS));
     MetaDataManager::refreshModulesCache(array_keys($modulesToBuild));
     $GLOBALS['log']->info(get_class($this) . "->build(): finished relationship installation");
 }
Ejemplo n.º 10
0
 protected function buildRelationshipCache()
 {
     global $beanList, $buildingRelCache;
     if ($buildingRelCache) {
         return;
     }
     $buildingRelCache = true;
     $relationships = $this->getRelationshipData();
     //Save it out
     sugar_mkdir(dirname($this->getCacheFile()), null, true);
     $out = "<?php \n \$relationships = " . var_export($relationships, true) . ";";
     sugar_file_put_contents_atomic($this->getCacheFile(), $out);
     // There are only certain times when the relationship cache needs to be
     // refreshed...
     //
     // If we have a cache, but no internal relationships yet, do NOT rebuild
     // the api cache. This is a first load of this class.
     //
     // If there is no cache, then do NOT rebuild the api cache since there is
     // nothing to rebuild.
     //
     // DO rebuild the cache if there is a cache, there is an internal relationships
     // property and it is different than $relationships
     $rebuildApiCache = false;
     $metaCacheKey = MetaDataManager::getManager()->getCachedMetadataHash();
     if (empty($metaCacheKey)) {
         $rebuildApiCache = !empty($this->relationships) && array_diff_key($this->relationships, $relationships) !== array();
     }
     $this->relationships = $relationships;
     if ($rebuildApiCache) {
         MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_RELATIONSHIPS));
     }
     // set the variable back to false, as we are now going to rebuild the vardefs since we have all the
     // relationships are loaded
     $buildingRelCache = false;
     //Now load all vardefs a second time populating the rel_calc_fields
     foreach ($beanList as $moduleName => $beanName) {
         // need to refresh the vardef so that the related calc fields are loaded
         VardefManager::loadVardef($moduleName, BeanFactory::getObjectName($moduleName), true);
     }
 }
Ejemplo n.º 11
0
 /**
  * Adds a custom field using a field object
  *
  * @param Field Object $field
  * @return boolean
  */
 public function addFieldObject(&$field)
 {
     $GLOBALS['log']->debug('adding field');
     $object_name = $this->module;
     $db_name = $field->name;
     $fmd = BeanFactory::getBean('EditCustomFields');
     $id = $fmd->retrieve($object_name . $db_name, true, false);
     $is_update = false;
     $label = strtoupper($field->label);
     if (!empty($id)) {
         $is_update = true;
     } else {
         $db_name = $this->getDBName($field->name);
         $field->name = $db_name;
     }
     $this->createCustomTable();
     $fmd->id = $object_name . $db_name;
     $fmd->custom_module = $object_name;
     $fmd->name = $db_name;
     $fmd->vname = $label;
     $fmd->type = $field->type;
     $fmd->help = $field->help;
     if (!empty($field->len)) {
         $fmd->len = $field->len;
     }
     // tyoung bug 15407 - was being set to $field->size so changes weren't being saved
     $fmd->required = $field->required ? 1 : 0;
     $fmd->default_value = $field->default;
     $fmd->ext1 = $field->ext1;
     $fmd->ext2 = $field->ext2;
     $fmd->ext3 = $field->ext3;
     $fmd->ext4 = isset($field->ext4) ? $field->ext4 : '';
     $fmd->comments = $field->comment;
     $fmd->massupdate = $field->massupdate;
     $fmd->importable = isset($field->importable) ? $field->importable : null;
     $fmd->duplicate_merge = $field->duplicate_merge;
     $fmd->audited = $field->audited;
     $fmd->reportable = $field->reportable ? 1 : 0;
     if (!$is_update) {
         $fmd->new_with_id = true;
     }
     if ($field) {
         if (!$is_update) {
             //Do two SQL calls here in this case
             //The first is to create the column in the custom table without the default value
             //The second is to modify the column created in the custom table to set the default value
             //We do this so that the existing entries in the custom table don't have the default value set
             $field->default = '';
             $field->default_value = '';
             // resetting default and default_value does not work for multienum and causes trouble for mssql
             // so using a temporary variable here to indicate that we don't want default for this query
             $field->no_default = 1;
             $query = $field->get_db_add_alter_table($this->bean->table_name . '_cstm');
             // unsetting temporary member variable
             unset($field->no_default);
             if (!empty($query)) {
                 $GLOBALS['db']->query($query, true, "Cannot create column");
                 $field->default = $fmd->default_value;
                 $field->default_value = $fmd->default_value;
                 $query = $field->get_db_modify_alter_table($this->bean->table_name . '_cstm');
                 if (!empty($query)) {
                     $GLOBALS['db']->query($query, true, "Cannot set default");
                 }
             }
         } else {
             $query = $field->get_db_modify_alter_table($this->bean->table_name . '_cstm');
             if (!empty($query)) {
                 $GLOBALS['db']->query($query, true, "Cannot modify field");
             }
         }
         $fmd->save();
         $this->buildCache($this->module);
         $this->saveExtendedAttributes($field, array_keys($fmd->field_defs));
         MetaDataManager::refreshModulesCache(array($this->module));
         MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_LABELS, MetaDataManager::MM_ORDEREDLABELS));
     }
     return true;
 }
Ejemplo n.º 12
0
 /**
  * Cleans out current metadata cache and rebuilds it for
  * each platform and visibility
  */
 public function repairMetadataAPICache($section = '')
 {
     // Refresh metadata for selected modules only if there selected modules
     if (is_array($this->module_list) && !empty($this->module_list) && !in_array(translate('LBL_ALL_MODULES'), $this->module_list)) {
         MetaDataFiles::clearModuleClientCache($this->module_list);
         MetaDataManager::refreshModulesCache($this->module_list);
     }
     // If there is a section named (like 'fields') refresh that section
     if (!empty($section)) {
         MetaDataManager::refreshSectionCache($section);
     } else {
         // Otherwise if the section is not a false nuke all caches and rebuild
         // the base metadata cache
         if ($section !== false) {
             MetaDataManager::clearAPICache(true, true);
             MetaDataManager::setupMetadata();
         }
     }
 }
Ejemplo n.º 13
0
    }
    SugarBean::createRelationshipMeta($rel_name, $db, $table, $rel_dictionary, '');
    if (empty($_REQUEST['silent'])) {
        echo $mod_strings['LBL_DONE'] . '<br>';
    }
}
//clean relationship cache..will be rebuilt upon first access.
if (empty($_REQUEST['silent'])) {
    echo $mod_strings['LBL_REBUILD_REL_DEL_CACHE'];
}
$rel = BeanFactory::getBean('Relationships');
$rel->rebuild_relationship_cache(array_keys($changedModules));
//////////////////////////////////////////////////////////////////////////////
// Remove the "Rebuild Relationships" red text message on admin logins
// Refresh relationships metadata section cache
MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_RELATIONSHIPS));
if (empty($_REQUEST['silent'])) {
    echo $mod_strings['LBL_REBUILD_REL_UPD_WARNING'];
}
// clear the database row if it exists (just to be sure)
$query = "DELETE FROM versions WHERE name='Rebuild Relationships'";
$log->info($query);
$db->query($query);
// insert a new database row to show the rebuild relationships is done
$id = create_guid();
$gmdate = gmdate('Y-m-d H:i:s');
$date_entered = db_convert("'{$gmdate}'", 'datetime');
$query = 'INSERT INTO versions (id, deleted, date_entered, date_modified, modified_user_id, created_by, name, file_version, db_version) ' . "VALUES ('{$id}', '0', {$date_entered}, {$date_entered}, '1', '1', 'Rebuild Relationships', '4.0.0', '4.0.0')";
$log->info($query);
$db->query($query);
// unset the session variable so it is not picked up in DisplayWarnings.php
Ejemplo n.º 14
0
            if (!empty($_POST['SAML_SLO'])) {
                $_POST['SAML_SLO'] = trim($_POST['SAML_SLO']);
                if (!filter_var($_POST['SAML_SLO'], FILTER_VALIDATE_URL)) {
                    $configurator->addError($config_strings['ERR_SAML_SLO_URL']);
                    break;
                }
            }
            if (empty($_POST['SAML_X509Cert'])) {
                $configurator->addError($config_strings['ERR_EMPTY_SAML_CERT']);
                break;
            }
        }
        $configurator->saveConfig();
        $focus->saveConfig();
        // Clean API cache since we may have changed the authentication settings
        MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_CONFIG));
        die("\n            <script>\n            var app = window.parent.SUGAR.App;\n            app.api.call('read', app.api.buildURL('ping'));\n            app.router.navigate('#bwc/index.php?module=Administration&action=index', {trigger:true, replace:true});\n            </script>");
    } while (false);
    // We did not succeed saving, but we still want to load data from post to display it
    $configurator->populateFromPost();
}
$focus->retrieveSettings();
require_once 'include/SugarLogger/SugarLogger.php';
$sugar_smarty = new Sugar_Smarty();
// if no IMAP libraries available, disable Save/Test Settings
if (!function_exists('imap_open')) {
    $sugar_smarty->assign('IE_DISABLED', 'DISABLED');
}
$sugar_smarty->assign('CONF', $config_strings);
$sugar_smarty->assign('MOD', $mod_strings);
$sugar_smarty->assign('APP', $app_strings);
Ejemplo n.º 15
0
 /**
  * @param Administration $admin
  * @param array $forecastsSettings
  * @param RestService $api
  * @throws SugarApiExceptionInvalidHash
  */
 protected function compareSettingsToDefaults(Administration $admin, $forecastsSettings, $api)
 {
     $defaultConfig = ForecastsDefaults::getDefaults();
     $missing_config = array_diff(array_keys($defaultConfig), array_keys($forecastsSettings));
     if (!empty($missing_config)) {
         foreach ($missing_config as $config) {
             $val = $defaultConfig[$config];
             if (is_array($val)) {
                 $val = json_encode($val);
             }
             $admin->saveSetting('Forecasts', $config, $val, $api->platform);
         }
         MetaDataManager::refreshModulesCache(array("Forecasts"));
         MetaDataManager::refreshSectionCache(array(MetaDataManager::MM_CONFIG));
         throw new SugarApiExceptionInvalidHash();
     }
 }