public function testAppendDropDown() { global $app_list_strings; $app_list_strings = array("TestList" => array("A" => "Option A", "B" => "Option B", "C" => "Option C")); require_once 'include/utils.php'; file_put_contents($this->testLangFile, "<?php\n\$exemptDropdowns[] = 'TestList';\n\$app_list_strings['TestList']['D'] = 'Option D';\n?>"); // Initially TestList should have 3 items $this->assertEquals(3, count($app_list_strings['TestList'])); $app_list_strings = _mergeCustomAppListStrings($this->testLangFile, $app_list_strings); // After merge with custom language file, TestList should have 4 items (after-fix behaviour) $this->assertEquals(4, count($app_list_strings['TestList'])); unlink($this->testLangFile); unset($GLOBALS['app_list_strings']); }
/** * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var. * * @param string $language specific language to load * @return array lang strings */ function return_app_list_strings_language($language) { global $app_list_strings; global $sugar_config; $cache_key = 'app_list_strings.' . $language; // Check for cached value $cache_entry = sugar_cache_retrieve($cache_key); if (!empty($cache_entry)) { return $cache_entry; } $default_language = $sugar_config['default_language']; $temp_app_list_strings = $app_list_strings; $langs = array(); if ($language != 'en_us') { $langs[] = 'en_us'; } if ($default_language != 'en_us' && $language != $default_language) { $langs[] = $default_language; } $langs[] = $language; $app_list_strings_array = array(); foreach ($langs as $lang) { $app_list_strings = array(); if (file_exists("include/language/{$lang}.lang.php")) { include "include/language/{$lang}.lang.php"; $GLOBALS['log']->info("Found language file: {$lang}.lang.php"); } if (file_exists("include/language/{$lang}.lang.override.php")) { include "include/language/{$lang}.lang.override.php"; $GLOBALS['log']->info("Found override language file: {$lang}.lang.override.php"); } if (file_exists("include/language/{$lang}.lang.php.override")) { include "include/language/{$lang}.lang.php.override"; $GLOBALS['log']->info("Found override language file: {$lang}.lang.php.override"); } $app_list_strings_array[] = $app_list_strings; } $app_list_strings = array(); foreach ($app_list_strings_array as $app_list_strings_item) { $app_list_strings = sugarArrayMerge($app_list_strings, $app_list_strings_item); } foreach ($langs as $lang) { if (file_exists("custom/application/Ext/Language/{$lang}.lang.ext.php")) { $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/{$lang}.lang.ext.php", $app_list_strings); $GLOBALS['log']->info("Found extended language file: {$lang}.lang.ext.php"); } if (file_exists("custom/include/language/{$lang}.lang.php")) { include "custom/include/language/{$lang}.lang.php"; $GLOBALS['log']->info("Found custom language file: {$lang}.lang.php"); } } if (!isset($app_list_strings)) { $GLOBALS['log']->fatal("Unable to load the application language file for the selected language ({$language}) or the default language ({$default_language}) or the en_us language"); return null; } $return_value = $app_list_strings; $app_list_strings = $temp_app_list_strings; sugar_cache_put($cache_key, $return_value); return $return_value; }
/** * fix_dropdown_list * This method attempts to fix dropdown lists that were incorrectly named. * There were versions of SugarCRM that did not enforce naming convention rules * for the dropdown list field name. This method attempts to resolve that by * fixing the language files that may have been affected and then updating the * fields_meta_data table accordingly. It also refreshes any vardefs that may * have been affected. * */ function fix_dropdown_list() { if (file_exists('custom/include/language')) { $files = array(); $affected_modules = array(); $affected_keys = array(); getFiles($files, 'custom/include/language', '/\\.php$/i'); foreach ($files as $file) { if (file_exists($file . '.bak')) { $bak_mod_time = filemtime($file . '.bak'); $php_mod_time = filemtime($file); //We're saying if the .php file was modified 30 seconds no more than php.bak file then we //run these additional cleanup checks if ($php_mod_time - $bak_mod_time < 30) { $app_list_strings = array(); $GLOBALS['app_list_strings'] = array(); require $file . '.bak'; $bak_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']); $app_list_strings = array(); $GLOBALS['app_list_strings'] = array(); require $file; $php_app_list_strings = array_merge($app_list_strings, $GLOBALS['app_list_strings']); //Get the file contents $contents = file_get_contents($file); //Now simulate a fix for the file before we compare w/ the .php file //we also append to the $contents foreach ($bak_app_list_strings as $key => $entry) { if (preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) { $new_key = preg_replace('/[^A-Za-z_]/', '_', $key); $bak_app_list_strings[$new_key] = $bak_app_list_strings[$key]; unset($bak_app_list_strings[$key]); //Now if the entry doesn't exists in the .php file, then add to contents if (!isset($php_app_list_strings[$new_key])) { $contents .= "\n\$GLOBALS['app_list_strings']['{$new_key}'] = " . var_export_helper($bak_app_list_strings[$new_key]) . ";"; } } //if } //foreach //Now load the .php file to do the comparison foreach ($php_app_list_strings as $key => $entry) { if (isset($bak_app_list_strings[$key])) { $diff = array_diff($bak_app_list_strings[$key], $entry); if (!empty($diff)) { //There is a difference, so copy the $bak_app_list_strings version into the .php file $contents .= "\n\$GLOBALS['app_list_strings']['{$key}'] = " . var_export_helper($bak_app_list_strings[$key]) . ";"; } //if } //if } //foreach //Now write out the file contents //Create backup just in case copy($file, $file . '.php_bak'); $fp = @sugar_fopen($file, 'w'); if ($fp) { fwrite($fp, $contents); fclose($fp); } else { $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list for {$file}"); } //if-else } } unset($GLOBALS['app_strings']); unset($GLOBALS['app_list_strings']); $app_list_strings = array(); require $file; $touched = false; $contents = file_get_contents($file); if (!isset($GLOBALS['app_list_strings'])) { $GLOBALS['app_list_strings'] = $app_list_strings; } else { $GLOBALS['app_list_strings'] = array_merge($app_list_strings, $GLOBALS['app_list_strings']); } if (isset($GLOBALS['app_list_strings']) && is_array($GLOBALS['app_list_strings'])) { foreach ($GLOBALS['app_list_strings'] as $key => $entry) { if (preg_match('/([^A-Za-z_])/', $key, $matches) && is_array($entry)) { $result = $GLOBALS['db']->query("SELECT custom_module FROM fields_meta_data WHERE ext1 = '{$key}'"); if (!empty($result)) { while ($row = $GLOBALS['db']->fetchByAssoc($result)) { $custom_module = $row['custom_module']; if (!empty($GLOBALS['beanList'][$custom_module])) { $affected_modules[$custom_module] = $GLOBALS['beanList'][$custom_module]; } } //while } //Replace all invalid characters with '_' character $new_key = preg_replace('/[^A-Za-z_]/', '_', $key); $affected_keys[$key] = $new_key; $GLOBALS['app_list_strings'][$new_key] = $GLOBALS['app_list_strings'][$key]; unset($GLOBALS['app_list_strings'][$key]); $pattern_match = "/(\\[\\s*\\'{$key}\\'\\s*\\])/"; $new_key = "['{$new_key}']"; $out = preg_replace($pattern_match, $new_key, $contents); $contents = $out; $touched = true; } //if } //foreach //This is a check for g => h instances where the file contents were incorrectly written //and also fixes the scenario where via a UI upgrade, the app_list_strings were incorrectly //merged with app_list_strings variables declared elsewhere if (!$touched) { if (preg_match('/\\$GLOBALS\\s*\\[\\s*[\\"|\']app_list_strings[\\"|\']\\s*\\]\\s*=\\s*array\\s*\\(/', $contents)) { //Now also remove all the non-custom labels that were added if (preg_match('/language\\/([^\\.]+)\\.lang\\.php$/', $file, $matches)) { $language = $matches[1]; $app_list_strings = array(); if (file_exists("include/language/{$language}.lang.php")) { include "include/language/{$language}.lang.php"; } if (file_exists("include/language/{$language}.lang.override.php")) { $app_list_strings = _mergeCustomAppListStrings("include/language/{$language}.lang.override.php", $app_list_strings); } if (file_exists("custom/application/Ext/Language/{$language}.ext.lang.php")) { $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/{$language}.ext.lang.php", $app_list_strings); } if (file_exists("custom/application/Ext/Language/{$language}.lang.ext.php")) { $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/{$language}.lang.ext.php", $app_list_strings); } $all_non_custom_include_language_strings = $app_strings; $all_non_custom_include_language_list_strings = $app_list_strings; $unset_keys = array(); if (!empty($GLOBALS['app_list_strings'])) { foreach ($GLOBALS['app_list_strings'] as $key => $value) { $diff = array(); if (isset($all_non_custom_include_language_list_strings[$key])) { $diff = array_diff($all_non_custom_include_language_list_strings[$key], $GLOBALS['app_list_strings'][$key]); } if (!empty($all_non_custom_include_language_list_strings[$key]) && empty($diff)) { $unset_keys[] = $key; } } } foreach ($unset_keys as $key) { unset($GLOBALS['app_list_strings'][$key]); } if (!empty($GLOBALS['app_strings'])) { foreach ($GLOBALS['app_strings'] as $key => $value) { if (!empty($all_non_custom_include_language_strings[$key])) { unset($GLOBALS['app_strings'][$key]); } } } } //if(preg_match...) $out = "<?php \n"; if (!empty($GLOBALS['app_strings'])) { foreach ($GLOBALS['app_strings'] as $key => $entry) { $out .= "\n\$GLOBALS['app_strings']['{$key}']=" . var_export_helper($entry) . ";"; } } foreach ($GLOBALS['app_list_strings'] as $key => $entry) { $out .= "\n\$GLOBALS['app_list_strings']['{$key}']=" . var_export_helper($entry) . ";"; } //foreach $touched = true; } //if(preg_match...) } //if(!$touched) if ($touched) { //Create a backup just in case copy($file, $file . '.bak'); $fp = @sugar_fopen($file, 'w'); if ($fp) { fwrite($fp, $out); fclose($fp); } else { //If we can't update the file, just return $GLOBALS['log']->error("Unable to update file contents in fix_dropdown_list."); return; } } //if($touched) } //if } //foreach($files) //Update db entries (the order matters here... need to process database changes first) if (!empty($affected_keys)) { foreach ($affected_keys as $old_key => $new_key) { $GLOBALS['db']->query("UPDATE fields_meta_data SET ext1 = '{$new_key}' WHERE ext1 = '{$old_key}'"); } } //Update vardef files for affected modules if (!empty($affected_modules)) { foreach ($affected_modules as $module => $object) { VardefManager::refreshVardefs($module, $object); } } } }
/** This function retrieves an application language file and returns the array of strings included in the $app_list_strings var. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. * All Rights Reserved. * Contributor(s): ______________________________________.. * If you are using the current language, do not call this function unless you are loading it for the first time */ function return_app_list_strings_language($language) { global $app_list_strings; global $sugar_config; $cache_key = 'app_list_strings.' . $language; // Check for cached value $cache_entry = sugar_cache_retrieve($cache_key); if (!empty($cache_entry)) { return $cache_entry; } $default_language = $sugar_config['default_language']; $temp_app_list_strings = $app_list_strings; $language_used = $language; include "include/language/en_us.lang.php"; $en_app_list_strings = array(); if ($language_used != $default_language) { require "include/language/{$default_language}.lang.php"; if (file_exists("include/language/{$default_language}.lang.override.php")) { include "include/language/{$default_language}.lang.override.php"; } if (file_exists("include/language/{$default_language}.lang.php.override")) { include "include/language/{$default_language}.lang.php.override"; } $en_app_list_strings = $app_list_strings; } include "include/language/{$language}.lang.php"; if (file_exists("include/language/{$language}.lang.override.php")) { include "include/language/{$language}.lang.override.php"; } if (file_exists("include/language/{$language}.lang.php.override")) { include "include/language/{$language}.lang.php.override"; } // cn: bug 6048 - merge en_us with requested language if (!empty($en_app_list_strings)) { $app_list_strings = sugarArrayMerge($en_app_list_strings, $app_list_strings); } if (file_exists("custom/application/Ext/Language/en_us.lang.ext.php")) { $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/en_us.lang.ext.php", $app_list_strings); } if ($language_used != $default_language) { if (file_exists("custom/application/Ext/Language/{$default_language}.lang.ext.php")) { $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/{$default_language}.lang.ext.php", $app_list_strings); $GLOBALS['log']->info("Found extended language file: {$default_language}.lang.ext.php"); } if (file_exists("custom/include/language/{$default_language}.lang.php")) { include "custom/include/language/{$default_language}.lang.php"; $GLOBALS['log']->info("Found custom language file: {$default_language}.lang.php"); } } if (file_exists("custom/application/Ext/Language/{$language}.lang.ext.php")) { $app_list_strings = _mergeCustomAppListStrings("custom/application/Ext/Language/{$language}.lang.ext.php", $app_list_strings); $GLOBALS['log']->info("Found extended language file: {$language}.lang.ext.php"); } if (file_exists("custom/include/language/{$language}.lang.php")) { include "custom/include/language/{$language}.lang.php"; $GLOBALS['log']->info("Found custom language file: {$language}.lang.php"); } if (!isset($app_list_strings)) { $GLOBALS['log']->warn("Unable to find the application language file for language: " . $language); $language_used = $default_language; $app_list_strings = $en_app_list_strings; } if (!isset($app_list_strings)) { $GLOBALS['log']->fatal("Unable to load the application language file for the selected language({$language}) or the default language({$default_language})"); return null; } $return_value = $app_list_strings; $app_list_strings = $temp_app_list_strings; sugar_cache_put($cache_key, $return_value); return $return_value; }
/** * This function retrieves an application language file and returns the array of strings included in the $app_list_strings var. * * @param string $language specific language to load * @param bool $useCache optional use cache for store language data array * @return array lang strings */ function return_app_list_strings_language($language, $useCache = true) { global $app_list_strings; global $sugar_config; //$useCache added to fix CRYS-459 memory limit if ($useCache) { $cache_key = 'app_list_strings.' . $language; // Check for cached value $cache_entry = sugar_cache_retrieve($cache_key); if (!empty($cache_entry)) { return $cache_entry; } } $default_language = !empty($sugar_config['default_language']) ? $sugar_config['default_language'] : $language; $temp_app_list_strings = $app_list_strings; $langs = array('en_us'); if ($default_language != 'en_us') { $langs[] = $default_language; } if (!in_array($language, $langs) || $default_language != 'en_us' && $language == 'en_us') { $langs[] = $language; } $app_list_strings_array = array(); //Merge language files together foreach ($langs as $key => $lang) { $app_list_strings_state = $app_list_strings; foreach (SugarAutoLoader::existing("include/language/{$lang}.lang.php", "include/language/{$lang}.lang.override.php", "include/language/{$lang}.lang.php.override") as $file) { include $file; $GLOBALS['log']->info("Found language file: {$file}"); } $app_list_strings_array[$lang] = $app_list_strings; //Return to previous state unless we are on first iteration and do an intersect merge if ($key > 0) { $app_list_strings = $app_list_strings_state; //In case a custom file doesn't exist for the expected language, we want the custom lists from the default language //(if there are key additions/deletions) but we want strings in our expected language (as much as possible). $app_list_strings = sugarArrayIntersectMerge($app_list_strings, $app_list_strings_array[$lang]); } $files = SugarAutoLoader::existing("custom/application/Ext/Language/{$lang}.lang.ext.php", "custom/include/language/{$lang}.lang.php"); $files = sortExtensionFiles($files); foreach ($files as $file) { $app_list_strings = _mergeCustomAppListStrings($file, $app_list_strings); $GLOBALS['log']->info("Found language file: {$file}"); } } if (!isset($app_list_strings)) { $GLOBALS['log']->fatal("Unable to load the application language file for the selected language ({$language}) or the default language ({$default_language}) or the en_us language"); return null; } $return_value = $app_list_strings; $app_list_strings = $temp_app_list_strings; //Add to the app_list_strings the list of language available in the application. $return_value['available_language_dom'] = get_languages(); if ($useCache) { sugar_cache_put($cache_key, $return_value); } return $return_value; }