2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM Community Edition is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
39 require_once('modules/Studio/DropDowns/DropDownHelper.php');
40 require_once 'modules/ModuleBuilder/parsers/parser.label.php' ;
45 * Selected language user is renaming for (eg. en_us).
49 private $selectedLanguage;
52 * An array containing the modules which should be renamed.
56 private $changedModules;
59 * An array containing the modules which have had their module strings modified as part of the
64 private $renamedModules = array();
68 * An array containing the modules and their labels to be changed when module is renamed.
70 private static $labelMap = array(
72 array('name' => 'LBL_CAMPAIGNS', 'type' => 'plural', 'source' => 'Campaigns'),
73 array('name' => 'LBL_CAMPAIGN_ID', 'type' => 'singular', 'source' => 'Campaigns'),
74 array('name' => 'LBL_PARENT_ACCOUNT_ID', 'type' => 'singular', 'source' => 'Accounts'),
75 array('name' => 'LBL_PROSPECT_LIST', 'type' => 'singular', 'source' => 'Prospects'),
76 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Accounts'),
79 array('name' => 'LBL_LIST_FORM_TITLE', 'type' => 'singular', 'source' => 'Bugs'),
80 array('name' => 'LBL_LIST_MY_BUGS', 'type' => 'plural', 'source' => 'Bugs'),
81 array('name' => 'LBL_SEARCH_FORM_TITLE', 'type' => 'singular', 'source' => 'Bugs'),
82 array('name' => 'LNK_BUG_LIST', 'type' => 'plural', 'source' => 'Bugs'),
83 array('name' => 'LNK_BUG_REPORTS', 'type' => 'singular', 'source' => 'Bugs'),
84 array('name' => 'LNK_IMPORT_BUGS', 'type' => 'plural', 'source' => 'Bugs'),
85 array('name' => 'LNK_NEW_BUG', 'type' => 'singular', 'source' => 'Bugs'),
86 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Bugs'),
89 array('name' => 'LBL_LIST_CONTACT', 'type' => 'singular', 'source' => 'Contacts'),
90 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Calls'),
93 array('name' => 'LBL_ACCOUNTS', 'type' => 'plural', 'source' => 'Accounts'),
94 array('name' => 'LBL_CONTACTS', 'type' => 'plural', 'source' => 'Contacts'),
95 array('name' => 'LBL_LIST_CAMPAIGN_NAME', 'type' => 'singular', 'source' => 'Campaigns'),
96 array('name' => 'LBL_LOG_ENTRIES_CONTACT_TITLE', 'type' => 'plural', 'source' => 'Contacts'),
97 array('name' => 'LBL_LOG_ENTRIES_LEAD_TITLE', 'type' => 'plural', 'source' => 'Leads'),
98 array('name' => 'LBL_OPPORTUNITIES', 'type' => 'plural', 'source' => 'Opportunities'),
99 array('name' => 'LBL_PROSPECT_LIST_SUBPANEL_TITLE', 'type' => 'singular', 'source' => 'Targets'),
100 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Campaigns'),
103 array('name' => 'LBL_BUGS_SUBPANEL_TITLE', 'type' => 'plural', 'source' => 'Bugs'),
104 array('name' => 'LBL_LIST_ACCOUNT_NAME', 'type' => 'singular', 'source' => 'Accounts'),
105 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Cases'),
108 array('name' => 'LBL_BUGS_SUBPANEL_TITLE', 'type' => 'plural', 'source' => 'Bugs'),
109 array('name' => 'LBL_CAMPAIGN_LIST_SUBPANEL_TITLE', 'type' => 'plural', 'source' => 'Campaigns'),
110 array('name' => 'LBL_CONTRACTS', 'type' => 'plural', 'source' => 'Contracts'),
111 array('name' => 'LBL_LIST_ACCOUNT_NAME', 'type' => 'singular', 'source' => 'Accounts'),
112 array('name' => 'LBL_LEAD_SOURCE', 'type' => 'singular', 'source' => 'Leads'),
113 array('name' => 'LBL_OPPORTUNITIES', 'type' => 'singular', 'source' => 'Opportunities'),
114 array('name' => 'LBL_OPPORTUNITY_ROLE', 'type' => 'singular', 'source' => 'Opportunities'),
115 array('name' => 'LBL_OPPORTUNITY_ROLE_ID', 'type' => 'singular', 'source' => 'Opportunities'),
116 array('name' => 'LBL_PRODUCTS_TITLE', 'type' => 'plural', 'source' => 'Products'),
117 array('name' => 'LBL_PROSPECT_LIST', 'type' => 'singular', 'source' => 'Prospects'),
118 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Contacts'),
120 'Contracts' => array(
121 array('name' => 'LBL_CONTRACT_NAME', 'type' => 'singular', 'source' => 'Contracts'),
122 array('name' => 'LBL_CONTRACT_TERM', 'type' => 'singular', 'source' => 'Contracts'),
123 array('name' => 'LBL_DOCUMENTS', 'type' => 'plural', 'source' => 'Documents'),
124 array('name' => 'LBL_LIST_ACCOUNT_NAME', 'type' => 'singular', 'source' => 'Accounts'),
125 array('name' => 'LBL_LIST_CONTRACT_NAME', 'type' => 'singular', 'source' => 'Contracts'),
126 array('name' => 'LBL_OPPORTUNITY', 'type' => 'singular', 'source' => 'Opportunities'),
127 array('name' => 'LBL_OPPORTUNITY_NAME', 'type' => 'singular', 'source' => 'Opportunities'),
128 array('name' => 'LBL_SEARCH_FORM_TITLE', 'type' => 'singular', 'source' => 'Contracts'),
129 array('name' => 'LBL_TOTAL_CONTRACT_VALUE', 'type' => 'singular', 'source' => 'Contracts'),
130 array('name' => 'LBL_TOTAL_CONTRACT_VALUE_USDOLLAR', 'type' => 'singular', 'source' => 'Contracts'),
131 array('name' => 'LNK_NEW_CONTRACT', 'type' => 'singular', 'source' => 'Contracts'),
132 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Contracts'),
134 'Documents' => array(
135 array('name' => 'LBL_BUGS_SUBPANEL_TITLE', 'type' => 'plural', 'source' => 'Bugs'),
136 array('name' => 'LBL_CONTRACTS', 'type' => 'plural', 'source' => 'Contracts'),
137 array('name' => 'LBL_CONTRACT_NAME', 'type' => 'singular', 'source' => 'Contracts'),
138 array('name' => 'LBL_CONTRACT_STATUS', 'type' => 'singular', 'source' => 'Contracts'),
139 array('name' => 'LBL_DET_RELATED_DOCUMENT_VERSION', 'type' => 'singular', 'source' => 'Documents'),
140 array('name' => 'LBL_DET_TEMPLATE_TYPE', 'type' => 'singular', 'source' => 'Documents'),
141 array('name' => 'LBL_DOC_ID', 'type' => 'singular', 'source' => 'Documents'),
142 array('name' => 'LBL_DOC_NAME', 'type' => 'singular', 'source' => 'Documents'),
143 array('name' => 'LBL_DOC_REV_HEADER', 'type' => 'singular', 'source' => 'Documents'),
144 array('name' => 'LBL_DOC_URL', 'type' => 'singular', 'source' => 'Documents'),
145 array('name' => 'LBL_NAME', 'type' => 'singular', 'source' => 'Documents'),
146 array('name' => 'LBL_TEMPLATE_TYPE', 'type' => 'singular', 'source' => 'Documents'),
147 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Documents'),
149 'KBDocuments' => array(
150 array('name' => 'LBL_CASES', 'type' => 'plural', 'source' => 'Cases'),
151 array('name' => 'LBL_CONTRACTS', 'type' => 'plural', 'source' => 'Contracts'),
152 array('name' => 'LBL_CONTRACT_NAME', 'type' => 'plural', 'source' => 'Contracts'),
153 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'KBDocuments'),
156 array('name' => 'LNK_SELECT_###MODULE_PLURAL###', 'type' => 'singular', 'source' => 'Leads'),
157 array('name' => 'LNK_SELECT_###MODULE_SINGULAR###', 'type' => 'singular', 'source' => 'Leads'),
158 array('name' => 'LBL_ACCOUNT_DESCRIPTION', 'type' => 'singular', 'source' => 'Accounts'),
159 array('name' => 'LBL_ACCOUNT_ID', 'type' => 'singular', 'source' => 'Accounts'),
160 array('name' => 'LBL_ACCOUNT_NAME', 'type' => 'singular', 'source' => 'Accounts'),
161 array('name' => 'LBL_CAMPAIGN_ID', 'type' => 'singular', 'source' => 'Campaigns'),
162 array('name' => 'LBL_CAMPAIGN_LEAD', 'type' => 'plural', 'source' => 'Campaigns'),
163 array('name' => 'LBL_CAMPAIGN_LIST_SUBPANEL_TITLE', 'type' => 'plural', 'source' => 'Campaigns'),
164 array('name' => 'LBL_CONTACT_ID', 'type' => 'singular', 'source' => 'Contacts'),
165 array('name' => 'LBL_LEAD_SOURCE', 'type' => 'singular', 'source' => 'Leads'),
166 array('name' => 'LBL_LEAD_SOURCE_DESCRIPTION', 'type' => 'singular', 'source' => 'Leads'),
167 array('name' => 'LBL_LIST_ACCOUNT_NAME', 'type' => 'singular', 'source' => 'Accounts'),
168 array('name' => 'LBL_OPPORTUNITY_AMOUNT', 'type' => 'singular', 'source' => 'Opportunities'),
169 array('name' => 'LBL_OPPORTUNITY_ID', 'type' => 'singular', 'source' => 'Opportunities'),
170 array('name' => 'LBL_OPPORTUNITY_NAME', 'type' => 'singular', 'source' => 'Opportunities'),
171 array('name' => 'LBL_CONVERTED_ACCOUNT', 'type' => 'singular', 'source' => 'Accounts'),
172 array('name' => 'LNK_SELECT_ACCOUNTS', 'type' => 'singular', 'source' => 'Accounts'),
173 array('name' => 'LNK_NEW_ACCOUNT', 'type' => 'singular', 'source' => 'Accounts'),
174 array('name' => 'LBL_CONVERTED_CONTACT', 'type' => 'singular', 'source' => 'Contacts'),
175 array('name' => 'LBL_CONVERTED_OPP', 'type' => 'singular', 'source' => 'Opportunities'),
176 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Leads'),
179 array('name' => 'LBL_LIST_CONTACT', 'type' => 'singular', 'source' => 'Contacts'),
180 array('name' => 'LBL_LIST_JOIN_MEETING', 'type' => 'singular', 'source' => 'Meetings'),
181 array('name' => 'LBL_PASSWORD', 'type' => 'singular', 'source' => 'Meetings'),
182 array('name' => 'LBL_TYPE', 'type' => 'singular', 'source' => 'Meetings'),
183 array('name' => 'LBL_URL', 'type' => 'singular', 'source' => 'Meetings'),
184 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Meetings'),
187 array('name' => 'LBL_ACCOUNT_ID', 'type' => 'singular', 'source' => 'Accounts'),
188 array('name' => 'LBL_CASE_ID', 'type' => 'singular', 'source' => 'Cases'),
189 array('name' => 'LBL_CONTACT_ID', 'type' => 'singular', 'source' => 'Contacts'),
190 array('name' => 'LBL_LIST_CONTACT', 'type' => 'singular', 'source' => 'Contacts'),
191 array('name' => 'LBL_LIST_CONTACT_NAME', 'type' => 'singular', 'source' => 'Contacts'),
192 array('name' => 'LBL_NOTE_STATUS', 'type' => 'singular', 'source' => 'Notes'),
193 array('name' => 'LBL_OPPORTUNITY_ID', 'type' => 'singular', 'source' => 'Opportunities'),
194 array('name' => 'LBL_PRODUCT_ID', 'type' => 'singular', 'source' => 'Products'),
195 array('name' => 'LBL_QUOTE_ID', 'type' => 'singular', 'source' => 'Quotes'),
196 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Notes'),
198 'Opportunities' => array(
199 array('name' => 'LBL_ACCOUNT_ID', 'type' => 'singular', 'source' => 'Accounts'),
200 array('name' => 'LBL_AMOUNT', 'type' => 'singular', 'source' => 'Opportunities'),
201 array('name' => 'LBL_CAMPAIGN_OPPORTUNITY', 'type' => 'plural', 'source' => 'Campaigns'),
202 array('name' => 'LBL_CONTRACTS', 'type' => 'plural', 'source' => 'Contracts'),
203 array('name' => 'LBL_LEAD_SOURCE', 'type' => 'singular', 'source' => 'Leads'),
204 array('name' => 'LBL_LIST_ACCOUNT_NAME', 'type' => 'singular', 'source' => 'Accounts'),
205 array('name' => 'LBL_OPPORTUNITY_NAME', 'type' => 'singular', 'source' => 'Opportunities'),
206 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Opportunities'),
208 'ProductTemplates' => array(
209 array('name' => 'LBL_PRODUCT_ID', 'type' => 'singular', 'source' => 'Products'),
210 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'ProductTemplates'),
213 array('name' => 'LBL_ACCOUNT_ID', 'type' => 'singular', 'source' => 'Accounts'),
214 array('name' => 'LBL_CONTACT', 'type' => 'singular', 'source' => 'Contacts'),
215 array('name' => 'LBL_CONTACT_ID', 'type' => 'singular', 'source' => 'Contacts'),
216 array('name' => 'LBL_CONTRACTS', 'type' => 'plural', 'source' => 'Contacts'),
217 array('name' => 'LBL_LIST_ACCOUNT_NAME', 'type' => 'singular', 'source' => 'Accounts'),
218 array('name' => 'LBL_LIST_NAME', 'type' => 'singular', 'source' => 'Products'),
219 array('name' => 'LBL_NAME', 'type' => 'singular', 'source' => 'Products'),
220 array('name' => 'LBL_QUOTE_ID', 'type' => 'singular', 'source' => 'Quotes'),
221 array('name' => 'LBL_RELATED_PRODUCTS', 'type' => 'plural', 'source' => 'Products'),
222 array('name' => 'LBL_URL', 'type' => 'singular', 'source' => 'Products'),
223 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Products'),
225 'ProjectTask' => array(
226 array('name' => 'LBL_PARENT_NAME', 'type' => 'singular', 'source' => 'Projects'),
227 array('name' => 'LBL_PROJECT_ID', 'type' => 'singular', 'source' => 'Projects'),
228 array('name' => 'LBL_PROJECT_NAME', 'type' => 'singular', 'source' => 'Projects'),
229 array('name' => 'LBL_PROJECT_TASK_ID', 'type' => 'singular', 'source' => 'Projects'),
230 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'ProjectTask'),
233 array('name' => 'LBL_BUGS_SUBPANEL_TITLE', 'type' => 'plural', 'source' => 'Bugs'),
234 array('name' => 'LBL_CONTACTS_RESOURCE', 'type' => 'singular', 'source' => 'Contacts'),
235 array('name' => 'LBL_LIST_FORM_TITLE', 'type' => 'singular', 'source' => 'Projects'),
236 array('name' => 'LBL_OPPORTUNITIES', 'type' => 'plural', 'source' => 'Opportunities'),
237 array('name' => 'LBL_PROJECT_HOLIDAYS_TITLE', 'type' => 'singular', 'source' => 'Projects'),
238 array('name' => 'LBL_PROJECT_TASKS_SUBPANEL_TITLE', 'type' => 'singular', 'source' => 'Projects'),
239 array('name' => 'LBL_SEARCH_FORM_TITLE', 'type' => 'singular', 'source' => 'Projects'),
240 array('name' => 'LNK_NEW_PROJECT', 'type' => 'singular', 'source' => 'Projects'),
241 array('name' => 'LNK_PROJECT_LIST', 'type' => 'singular', 'source' => 'Projects'),
242 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Projects'),
245 array('name' => 'LBL_ACCOUNT_ID', 'type' => 'singular', 'source' => 'Accounts'),
246 array('name' => 'LBL_CONTRACTS', 'type' => 'plural', 'source' => 'Contracts'),
247 array('name' => 'LBL_LIST_ACCOUNT_NAME', 'type' => 'singular', 'source' => 'Accounts'),
248 array('name' => 'LBL_QUOTE_NUM', 'type' => 'singular', 'source' => 'Quotes'),
249 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Quotes'),
252 array('name' => 'LBL_ACCOUNT_NAME', 'type' => 'singular', 'source' => 'Accounts'),
253 array('name' => 'LBL_CAMPAIGN_ID', 'type' => 'plural', 'source' => 'Campaigns'),
254 array('name' => 'LBL_CAMPAIGN_LIST_SUBPANEL_TITLE', 'type' => 'singular', 'source' => 'Campaigns'),
255 array('name' => 'LBL_PROSPECT_LIST', 'type' => 'singular', 'source' => 'Prospects'),
256 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Targets'),
259 array('name' => 'LBL_CONTACT', 'type' => 'singular', 'source' => 'Contacts'),
260 array('name' => 'LBL_CONTACT_ID', 'type' => 'singular', 'source' => 'Contacts'),
261 array('name' => 'LBL_CONTACT_PHONE', 'type' => 'singular', 'source' => 'Contacts'),
262 array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Tasks'),
269 * @param string $options
272 public function process($options = '')
274 if($options == 'SaveDropDown')
282 * Main display function.
286 protected function display()
288 global $app_list_strings, $mod_strings;
291 require_once('modules/Studio/parsers/StudioParser.php');
292 $dh = new DropDownHelper();
294 $smarty = new Sugar_Smarty();
295 $smarty->assign('MOD', $GLOBALS['mod_strings']);
296 $title=getClassicModuleTitle($mod_strings['LBL_MODULE_NAME'], array("<a href='index.php?module=Administration&action=index'>".$mod_strings['LBL_MODULE_NAME']."</a>", $mod_strings['LBL_RENAME_TABS']), false);
297 $smarty->assign('title', $title);
299 $selected_lang = (!empty($_REQUEST['dropdown_lang'])?$_REQUEST['dropdown_lang']:$_SESSION['authenticated_user_language']);
300 if(empty($selected_lang))
302 $selected_lang = $GLOBALS['sugar_config']['default_language'];
305 if($selected_lang == $GLOBALS['current_language'])
307 $my_list_strings = $GLOBALS['app_list_strings'];
311 $my_list_strings = return_app_list_strings_language($selected_lang);
314 $selected_dropdown = $my_list_strings['moduleList'];
315 $selected_dropdown_singular = $my_list_strings['moduleListSingular'];
318 foreach($selected_dropdown as $key=>$value)
320 $singularValue = isset($selected_dropdown_singular[$key]) ? $selected_dropdown_singular[$key] : $value;
321 if($selected_lang != $_SESSION['authenticated_user_language'] && !empty($app_list_strings['moduleList']) && isset($app_list_strings['moduleList'][$key]))
323 $selected_dropdown[$key]=array('lang'=>$value, 'user_lang'=> '['.$app_list_strings['moduleList'][$key] . ']', 'singular' => $singularValue);
327 $selected_dropdown[$key]=array('lang'=>$value, 'singular' => $singularValue);
332 $selected_dropdown = $dh->filterDropDown('moduleList', $selected_dropdown);
334 $smarty->assign('dropdown', $selected_dropdown);
335 $smarty->assign('dropdown_languages', get_languages());
338 $buttons[] = array('text'=>$mod_strings['LBL_BTN_UNDO'],'actionScript'=>"onclick='jstransaction.undo()'" );
339 $buttons[] = array('text'=>$mod_strings['LBL_BTN_REDO'],'actionScript'=>"onclick='jstransaction.redo()'" );
340 $buttons[] = array('text'=>$mod_strings['LBL_BTN_SAVE'],'actionScript'=>"onclick='if(check_form(\"editdropdown\")){document.editdropdown.submit();}'");
341 $buttonTxt = StudioParser::buildImageButtons($buttons);
342 $smarty->assign('buttons', $buttonTxt);
343 $smarty->assign('dropdown_lang', $selected_lang);
345 $editImage = SugarThemeRegistry::current()->getImage( 'edit_inline', '');
346 $smarty->assign('editImage',$editImage);
347 $deleteImage = SugarThemeRegistry::current()->getImage( 'delete_inline', '');
348 $smarty->assign('deleteImage',$deleteImage);
349 $smarty->display("modules/Studio/wizards/RenameModules.tpl");
353 * Save function responsible executing all sub-save functions required to rename a module.
357 public function save($redirect = TRUE)
359 $this->selectedLanguage = (!empty($_REQUEST['dropdown_lang'])? $_REQUEST['dropdown_lang']:$_SESSION['authenticated_user_language']);
361 //Clear all relevant language caches
362 $this->clearLanguageCaches();
364 //Retrieve changes the user is requesting and store previous values for future use.
365 $this->changedModules = $this->getChangedModules();
367 //Change module, appStrings, subpanels, and related links.
368 $this->changeAppStringEntries()->changeAllModuleModStrings()->renameAllRelatedLinks()->renameAllSubpanels()->renameAllDashlets();
370 foreach (self::$labelMap as $module=>$labelsArr) {
371 $this->renameCertainModuleModStrings($module, $labelsArr);
374 //Refresh the page again so module tabs are changed as the save process happens after module tabs are already generated.
376 SugarApplication::redirect('index.php?action=wizard&module=Studio&wizard=StudioWizard&option=RenameTabs');
380 * Rename all subpanels within the application.
383 * @return RenameModules
385 private function renameAllSubpanels()
389 foreach($beanList as $moduleName => $beanName)
391 if( class_exists($beanName) )
393 $this->renameModuleSubpanel($moduleName, $beanName, $this->changedModules);
397 $GLOBALS['log']->error("Class $beanName does not exist, unable to rename.");
406 * Rename subpanels for a particular module.
408 * @param string $moduleName The name of the module to be renamed
409 * @param string $beanName The name of the SugarBean to be renamed.
412 private function renameModuleSubpanel($moduleName, $beanName)
414 $GLOBALS['log']->info("About to rename subpanel for module: $moduleName");
415 $bean = new $beanName();
416 //Get the subpanel def
417 $subpanelDefs = $this->getSubpanelDefs($bean);
419 if(empty($subpanelDefs))
421 $GLOBALS['log']->debug("Found empty subpanel defs for $moduleName");
425 $mod_strings = return_module_language($this->selectedLanguage, $moduleName);
426 $replacementStrings = array();
428 //Iterate over all subpanel entries and see if we need to make a change.
429 foreach($subpanelDefs as $subpanelName => $subpanelMetaData)
431 $GLOBALS['log']->debug("Examining subpanel definition for potential rename: $subpanelName ");
432 //For each subpanel def, check if they are in our changed modules set.
433 foreach($this->changedModules as $changedModuleName => $renameFields)
435 if( !( isset($subpanelMetaData['type']) && $subpanelMetaData['type'] == 'collection') //Dont bother with collections
436 && isset($subpanelMetaData['module']) && $subpanelMetaData['module'] == $changedModuleName && isset($subpanelMetaData['title_key']) )
438 $replaceKey = $subpanelMetaData['title_key'];
439 if( !isset($mod_strings[$replaceKey]) )
441 $GLOBALS['log']->info("No module string entry defined for: {$mod_strings[$replaceKey]}");
444 $oldStringValue = $mod_strings[$replaceKey];
445 //At this point we don't know if we should replace the string with the plural or singular version of the new
446 //strings so we'll try both but with the plural version first since it should be longer than the singular.
447 // The saved old strings are html decoded, so we need to decode the new string first before str_replace.
448 $replacedString = str_replace(html_entity_decode_utf8($renameFields['prev_plural'], ENT_QUOTES), $renameFields['plural'], $oldStringValue);
449 if ($replacedString == $oldStringValue) {
450 // continue to replace singular only if nothing been replaced yet
451 $replacedString = str_replace(html_entity_decode_utf8($renameFields['prev_singular'], ENT_QUOTES), $renameFields['singular'], $replacedString);
453 $replacementStrings[$replaceKey] = $replacedString;
458 //Now we can write out the replaced language strings for each module
459 if(count($replacementStrings) > 0)
461 $GLOBALS['log']->debug("Writing out labels for subpanel changes for module $moduleName, labels: " . var_export($replacementStrings,true));
462 ParserLabel::addLabels($this->selectedLanguage, $replacementStrings, $moduleName);
463 $this->renamedModules[$moduleName] = true;
468 * Retrieve the subpanel definitions for a given SugarBean object. Unforunately we can't reuse
469 * any of the SubPanelDefinion.php functions.
471 * @param SugarBean $bean
472 * @return array The subpanel definitions.
474 private function getSubpanelDefs($bean )
476 if(empty($bean->module_dir)) {
480 $layout_defs = array();
482 if ( file_exists( 'modules/' . $bean->module_dir . '/metadata/subpaneldefs.php') )
483 require('modules/' . $bean->module_dir . '/metadata/subpaneldefs.php');
485 if ( file_exists( 'custom/modules/' . $bean->module_dir . '/Ext/Layoutdefs/layoutdefs.ext.php'))
486 require('custom/modules/' . $bean->module_dir . '/Ext/Layoutdefs/layoutdefs.ext.php');
488 return isset($layout_defs[$bean->module_dir]['subpanel_setup']) ? $layout_defs[$bean->module_dir]['subpanel_setup'] : $layout_defs;
492 * Rename all related linked within the application
494 * @return RenameModules
496 private function renameAllRelatedLinks()
500 foreach($beanList as $moduleName => $beanName)
502 if( class_exists($beanName) )
504 $this->renameModuleRelatedLinks($moduleName, $beanName);
508 $GLOBALS['log']->fatal("Class $beanName does not exist, unable to rename.");
516 * Rename the related links within a module.
518 * @param string $moduleName The module to be renamed
519 * @param string $moduleClass The class name of the module to be renamed
522 private function renameModuleRelatedLinks($moduleName, $moduleClass)
524 $GLOBALS['log']->info("Begining to renameModuleRelatedLinks for $moduleClass\n");
525 $tmp = new $moduleClass;
526 if( ! method_exists($tmp, 'get_related_fields') )
528 $GLOBALS['log']->info("Unable to resolve linked fields for module $moduleClass ");
532 $linkedFields = $tmp->get_related_fields();
533 $mod_strings = return_module_language($this->selectedLanguage, $moduleName);
534 $replacementStrings = array();
536 foreach($linkedFields as $link => $linkEntry)
538 //For each linked field check if the module referenced to is in our changed module list.
539 foreach($this->changedModules as $changedModuleName => $renameFields)
541 if( isset($linkEntry['module']) && $linkEntry['module'] == $changedModuleName)
543 $GLOBALS['log']->debug("Begining to rename for link field {$link}");
544 if( !isset($mod_strings[$linkEntry['vname']]) )
546 $GLOBALS['log']->debug("No label attribute for link $link, continuing.");
550 $replaceKey = $linkEntry['vname'];
551 $oldStringValue = $mod_strings[$replaceKey];
552 // Use the plural value of the two only if it's longer and the old language string contains it,
553 // singular otherwise
554 if (strlen($renameFields['prev_plural']) > strlen($renameFields['prev_singular']) && strpos($oldStringValue, $renameFields['prev_plural']) !== false) {
560 $replacedString = str_replace(html_entity_decode_utf8($renameFields['prev_' . $key], ENT_QUOTES), $renameFields[$key], $oldStringValue);
561 $replacementStrings[$replaceKey] = $replacedString;
566 //Now we can write out the replaced language strings for each module
567 if(count($replacementStrings) > 0)
569 $GLOBALS['log']->debug("Writing out labels for link changes for module $moduleName, labels: " . var_export($replacementStrings,true));
570 ParserLabel::addLabels($this->selectedLanguage, $replacementStrings, $moduleName);
571 $this->renamedModules[$moduleName] = true;
576 * Clear all related language cache files.
580 private function clearLanguageCaches()
582 //remove the js language files
583 LanguageManager::removeJSLanguageFiles();
585 //remove lanugage cache files
586 LanguageManager::clearLanguageCache();
590 * Rename all module strings within the application for dashlets.
592 * @return RenameModules
594 private function renameAllDashlets()
596 //Load the Dashlet metadata so we know what needs to be changed
597 if(!is_file(sugar_cached('dashlets/dashlets.php')))
599 require_once('include/Dashlets/DashletCacheBuilder.php');
600 $dc = new DashletCacheBuilder();
604 include(sugar_cached('dashlets/dashlets.php'));
606 foreach($this->changedModules as $moduleName => $replacementLabels)
608 $this->changeModuleDashletStrings($moduleName, $replacementLabels, $dashletsFiles);
616 * Rename the title value for all dashlets associated with a particular module
619 private function changeModuleDashletStrings($moduleName, $replacementLabels, $dashletsFiles)
621 $GLOBALS['log']->debug("Beginning to change module dashlet labels for: $moduleName ");
622 $replacementStrings = array();
624 foreach($dashletsFiles as $dashletName => $dashletData)
626 if( isset($dashletData['module']) && $dashletData['module'] == $moduleName && file_exists($dashletData['meta']) )
628 require( $dashletData['meta'] );
629 $dashletTitle = $dashletMeta[$dashletName]['title'];
630 $currentModuleStrings = return_module_language($this->selectedLanguage, $moduleName);
631 $modStringKey = array_search($dashletTitle,$currentModuleStrings);
632 if($modStringKey !== FALSE)
634 $replacedString = str_replace(html_entity_decode_utf8($replacementLabels['prev_plural'], ENT_QUOTES), $replacementLabels['plural'], $dashletTitle);
635 if ($replacedString == $dashletTitle) {
636 $replacedString = str_replace(html_entity_decode_utf8($replacementLabels['prev_singular'], ENT_QUOTES), $replacementLabels['singular'], $replacedString);
638 $replacementStrings[$modStringKey] = $replacedString;
643 //Now we can write out the replaced language strings for each module
644 if(count($replacementStrings) > 0)
646 $GLOBALS['log']->debug("Writing out labels for dashlet changes for module $moduleName, labels: " . var_export($replacementStrings,true));
647 ParserLabel::addLabels($this->selectedLanguage, $replacementStrings, $moduleName);
653 * Rename all module strings within the application.
655 * @return RenameModules
657 private function changeAllModuleModStrings()
659 foreach($this->changedModules as $moduleName => $replacementLabels)
661 $this->changeModuleModStrings($moduleName, $replacementLabels);
668 * Rename all module strings within the leads module.
670 * @param string $targetModule The name of the module that owns the labels to be changed.
671 * @param array $labelKeysToReplace The labels to be changed.
672 * @return RenameModules
674 private function renameCertainModuleModStrings($targetModule, $labelKeysToReplace)
676 $GLOBALS['log']->debug("Beginning to rename labels for $targetModule module");
677 foreach($this->changedModules as $moduleName => $replacementLabels)
679 $this->changeCertainModuleModStrings($moduleName, $replacementLabels, $targetModule, $labelKeysToReplace);
686 * For a particular module, rename any relevant module strings that need to be replaced.
688 * @param string $moduleName The name of the module to be renamed.
689 * @param $replacementLabels
690 * @param string $targetModule The name of the module that owns the labels to be changed.
691 * @param array $labelKeysToReplace The labels to be changed.
694 private function changeCertainModuleModStrings($moduleName, $replacementLabels, $targetModule, $labelKeysToReplace)
696 $GLOBALS['log']->debug("Beginning to change module labels for : $moduleName");
697 $currentModuleStrings = return_module_language($this->selectedLanguage, $targetModule);
699 $replacedLabels = array();
700 foreach($labelKeysToReplace as $entry)
702 if (!isset($entry['source']) || $entry['source'] != $moduleName) {
703 // skip this entry if the source module does not match the module being renamed
707 $formattedLanguageKey = $this->formatModuleLanguageKey($entry['name'], $replacementLabels);
709 //If the static of dynamic key exists it should be replaced.
710 if( isset($currentModuleStrings[$formattedLanguageKey]) )
712 $oldStringValue = $currentModuleStrings[$formattedLanguageKey];
713 $newStringValue = $this->replaceSingleLabel($oldStringValue, $replacementLabels, $entry);
714 if ($oldStringValue != $newStringValue) {
715 $replacedLabels[$formattedLanguageKey] = $newStringValue;
721 ParserLabel::addLabels($this->selectedLanguage, $replacedLabels, $targetModule);
722 $this->renamedModules[$targetModule] = true;
727 * For a particular module, rename any relevant module strings that need to be replaced.
729 * @param string $moduleName The name of the module to be renamed.
730 * @param $replacementLabels
733 private function changeModuleModStrings($moduleName, $replacementLabels)
735 $GLOBALS['log']->info("Begining to change module labels for: $moduleName");
736 $currentModuleStrings = return_module_language($this->selectedLanguage, $moduleName);
737 $labelKeysToReplace = array(
738 array('name' => 'LNK_NEW_RECORD', 'type' => 'plural'), //Module built modules, Create <moduleName>
739 array('name' => 'LNK_LIST', 'type' => 'plural'), //Module built modules, View <moduleName>
740 array('name' => 'LNK_NEW_###MODULE_SINGULAR###', 'type' => 'singular'),
741 array('name' => 'LNK_###MODULE_SINGULAR###_LIST', 'type' => 'plural'),
742 array('name' => 'LNK_###MODULE_SINGULAR###_REPORTS', 'type' => 'singular'),
743 array('name' => 'LNK_IMPORT_VCARD', 'type' => 'singular'),
744 array('name' => 'LNK_IMPORT_###MODULE_PLURAL###', 'type' => 'plural'),
745 array('name' => 'MSG_SHOW_DUPLICATES', 'type' => 'singular', 'case' => 'both'),
746 array('name' => 'LBL_SAVE_###MODULE_SINGULAR###', 'type' => 'singular'),
747 array('name' => 'LBL_LIST_FORM_TITLE', 'type' => 'singular'), //Popup title
748 array('name' => 'LBL_SEARCH_FORM_TITLE', 'type' => 'singular'), //Popup title
751 $replacedLabels = array();
752 foreach($labelKeysToReplace as $entry)
754 $formattedLanguageKey = $this->formatModuleLanguageKey($entry['name'], $replacementLabels);
756 //If the static of dynamic key exists it should be replaced.
757 if( isset($currentModuleStrings[$formattedLanguageKey]) )
759 $oldStringValue = $currentModuleStrings[$formattedLanguageKey];
760 $replacedLabels[$formattedLanguageKey] = $this->replaceSingleLabel($oldStringValue, $replacementLabels, $entry);
761 if( isset($entry['case']) && $entry['case'] == 'both')
763 $replacedLabels[$formattedLanguageKey] = $this->replaceSingleLabel($replacedLabels[$formattedLanguageKey], $replacementLabels, $entry, 'strtolower');
769 ParserLabel::addLabels($this->selectedLanguage, $replacedLabels, $moduleName);
770 $this->renamedModules[$moduleName] = true;
774 * Format our dynamic keys containing module strings to a valid key depending on the module.
776 * @param string $unformatedKey
777 * @param string $replacementStrings
780 private function formatModuleLanguageKey($unformatedKey, $replacementStrings)
782 $unformatedKey = str_replace('###MODULE_SINGULAR###', strtoupper($replacementStrings['key_singular']), $unformatedKey);
783 return str_replace('###MODULE_PLURAL###', strtoupper($replacementStrings['key_plural']), $unformatedKey);
788 * Replace a label with a new value based on metadata which specifies the label as either singular or plural.
790 * @param string $oldStringValue
791 * @param string $replacementLabels
792 * @param array $replacementMetaData
795 private function replaceSingleLabel($oldStringValue, $replacementLabels, $replacementMetaData, $modifier = '')
797 $replaceKey = 'prev_' . $replacementMetaData['type'];
798 $search = html_entity_decode_utf8($replacementLabels[$replaceKey], ENT_QUOTES);
799 $replace = $replacementLabels[$replacementMetaData['type']];
800 if( !empty($modifier) )
802 $search = call_user_func($modifier, $search);
803 $replace = call_user_func($modifier, $replace);
807 // If nothing was replaced - try to replace original string
810 $result = str_replace($search, $replace, $oldStringValue, $replaceCount);
812 $replaceKey = 'key_' . $replacementMetaData['type'];
813 $search = html_entity_decode_utf8($replacementLabels[$replaceKey], ENT_QUOTES);
814 $result = str_replace($search, $replace, $oldStringValue, $replaceCount);
821 * Save changes to the module names to the app string entries for both the moduleList and moduleListSingular entries.
823 * @return RenameModules
825 private function changeAppStringEntries()
827 $GLOBALS['log']->debug('Begining to save app string entries');
828 //Save changes to the moduleList app string entry
829 DropDownHelper::saveDropDown($_REQUEST);
831 //Save changes to the moduleListSingular app string entry
832 $newParams = array();
833 $newParams['dropdown_name'] = 'moduleListSingular';
834 $newParams['dropdown_lang'] = isset($_REQUEST['dropdown_lang']) ? $_REQUEST['dropdown_lang'] : '';
835 $newParams['use_push'] = true;
836 DropDownHelper::saveDropDown($this->createModuleListSingularPackage($newParams, $this->changedModules));
838 //Save changes to the "*type_display*" app_list_strings entry.
839 global $app_list_strings;
841 $typeDisplayList = getTypeDisplayList();
843 foreach (array_keys($this->changedModules)as $moduleName)
845 foreach($typeDisplayList as $typeDisplay)
847 if(isset($app_list_strings[$typeDisplay]) && isset($app_list_strings[$typeDisplay][$moduleName]))
849 $newParams['dropdown_name'] = $typeDisplay;
850 DropDownHelper::saveDropDown($this->createModuleListSingularPackage($newParams, array($moduleName => $this->changedModules[$moduleName])));
858 * Create an array entry that can be passed to the DropDownHelper:saveDropDown function so we can re-utilize
861 * @param array $params
862 * @param array $changedModules
865 private function createModuleListSingularPackage($params, $changedModules)
868 foreach($changedModules as $moduleName => $package)
870 $singularString = $package['singular'];
872 $params['slot_' . $count] = $count;
873 $params['key_' . $count] = $moduleName;
874 $params['value_' . $count] = $singularString;
875 $params['delete_' . $count] = '';
885 * Determine which modules have been updated and return an array with the module name as the key
886 * and the singular/plural entries as the value.
890 private function getChangedModules()
893 $allModuleEntries = array();
897 $selected_lang = (!empty($params['dropdown_lang'])?$params['dropdown_lang']:$_SESSION['authenticated_user_language']);
898 $current_app_list_string = return_app_list_strings_language($selected_lang);
900 while(isset($params['slot_' . $count]))
902 $index = $params['slot_' . $count];
904 $key = (isset($params['key_' . $index]))?SugarCleaner::stripTags($params['key_' . $index]): 'BLANK';
905 $value = (isset($params['value_' . $index]))?SugarCleaner::stripTags($params['value_' . $index]): '';
906 $svalue = (isset($params['svalue_' . $index]))?SugarCleaner::stripTags($params['svalue_' . $index]): $value;
911 $value = trim($value);
912 $svalue = trim($svalue);
914 //If the module key dne then do not continue with this rename.
915 if( isset($current_app_list_string['moduleList'][$key]) )
916 $allModuleEntries[$key] = array('s' => $svalue, 'p' => $value);
918 $_REQUEST['delete_' . $count] = TRUE;
925 foreach($allModuleEntries as $k => $e)
929 $prev_plural = $current_app_list_string['moduleList'][$k];
930 $prev_singular = isset($current_app_list_string['moduleListSingular'][$k]) ? $current_app_list_string['moduleListSingular'][$k] : $prev_plural;
931 if( strcmp($prev_plural, $pvalue) != 0 || (strcmp($prev_singular, $svalue) != 0) )
933 $results[$k] = array('singular' => $svalue, 'plural' => $pvalue, 'prev_singular' => $prev_singular, 'prev_plural' => $prev_plural,
934 'key_plural' => $k, 'key_singular' => $this->getModuleSingularKey($k)
945 * Return the 'singular' name of a module (Eg. Opportunity for Opportunities) given a moduleName which is a key
946 * in the app string moduleList array. If no entry is found, simply return the moduleName as this is consistant with modules
947 * built by moduleBuilder.
949 * @param string $moduleName
950 * @return string The 'singular' name of a module.
952 private function getModuleSingularKey($moduleName)
954 $className = isset($GLOBALS['beanList'][$moduleName]) ? $GLOBALS['beanList'][$moduleName] : null;
955 if( is_null($className) || ! class_exists($className) )
957 $GLOBALS['log']->error("Unable to get module singular key for class: $className");
961 $tmp = new $className();
962 if( property_exists($tmp, 'object_name') )
963 return $tmp->object_name;
969 * Return an array of the modules whos mod_strings have been modified.
973 public function getRenamedModules()
975 return $this->renamedModules;