]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/Studio/wizards/RenameModules.php
Release 6.5.16
[Github/sugarcrm.git] / modules / Studio / wizards / RenameModules.php
1 <?php
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.
6  * 
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.
13  * 
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
17  * details.
18  * 
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
22  * 02110-1301 USA.
23  * 
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.
26  * 
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.
30  * 
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  ********************************************************************************/
37
38
39 require_once('modules/Studio/DropDowns/DropDownHelper.php');
40 require_once 'modules/ModuleBuilder/parsers/parser.label.php' ;
41
42 class RenameModules
43 {
44     /**
45      * Selected language user is renaming for (eg. en_us).
46      *
47      * @var string
48      */
49     private $selectedLanguage;
50
51     /**
52      * An array containing the modules which should be renamed.
53      *
54      * @var array
55      */
56     private $changedModules;
57
58     /**
59      * An array containing the modules which have had their module strings modified as part of the
60      * renaming process.
61      *
62      * @var array
63      */
64     private $renamedModules = array();
65
66
67     /**
68      * An array containing the modules and their labels to be changed when module is renamed.
69      */
70     private static $labelMap = array(
71         'Accounts' => 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'),
77         ),
78         'Bugs' => array(
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'),
87         ),
88         'Calls' => array(
89             array('name' => 'LBL_LIST_CONTACT', 'type' => 'singular', 'source' => 'Contacts'),
90             array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'Calls'),
91         ),
92         'Campaigns' => array(
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'),
101         ),
102         'Cases' => array(
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'),
106         ),
107         'Contacts' => array(
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'),
119         ),
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'),
133         ),
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'),
148         ),
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'),
154         ),
155         'Leads' => array(
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'),
177         ),
178         'Meetings' => array(
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'),
185         ),
186         'Notes' => array(
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'),
197         ),
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'),
207         ),
208         'ProductTemplates' => array(
209             array('name' => 'LBL_PRODUCT_ID', 'type' => 'singular', 'source' => 'Products'),
210             array('name' => 'LBL_MODULE_NAME', 'type' => 'plural', 'source' => 'ProductTemplates'),
211         ),
212         'Products' => array(
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'),
224         ),
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'),
231         ),
232         'Project' => array(
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'),
243         ),
244         'Quotes' => array(
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'),
250         ),
251         'Targets' => array(
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'),
257         ),
258         'Tasks' => array(
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'),
263         ),
264     );
265
266
267     /**
268      *
269      * @param string $options
270      * @return void
271      */
272     public function process($options = '')
273     {
274         if($options == 'SaveDropDown')
275             $this->save();
276
277         $this->display();
278
279     }
280
281     /**
282      * Main display function.
283      *
284      * @return void
285      */
286     protected function display()
287     {
288         global $app_list_strings, $mod_strings;
289
290
291         require_once('modules/Studio/parsers/StudioParser.php');
292         $dh = new DropDownHelper();
293
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);
298
299         $selected_lang = (!empty($_REQUEST['dropdown_lang'])?$_REQUEST['dropdown_lang']:$_SESSION['authenticated_user_language']);
300         if(empty($selected_lang))
301         {
302             $selected_lang = $GLOBALS['sugar_config']['default_language'];
303         }
304
305         if($selected_lang == $GLOBALS['current_language'])
306         {
307             $my_list_strings = $GLOBALS['app_list_strings'];
308         }
309         else
310         {
311             $my_list_strings = return_app_list_strings_language($selected_lang);
312         }
313
314         $selected_dropdown = $my_list_strings['moduleList'];
315         $selected_dropdown_singular = $my_list_strings['moduleListSingular'];
316
317
318         foreach($selected_dropdown as $key=>$value)
319         {
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]))
322            {
323                 $selected_dropdown[$key]=array('lang'=>$value, 'user_lang'=> '['.$app_list_strings['moduleList'][$key] . ']', 'singular' => $singularValue);
324            }
325            else
326            {
327                $selected_dropdown[$key]=array('lang'=>$value, 'singular' => $singularValue);
328            }
329         }
330
331
332         $selected_dropdown = $dh->filterDropDown('moduleList', $selected_dropdown);
333
334         $smarty->assign('dropdown', $selected_dropdown);
335         $smarty->assign('dropdown_languages', get_languages());
336
337         $buttons = array();
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);
344
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");
350     }
351
352     /**
353      * Save function responsible executing all sub-save functions required to rename a module.
354      *
355      * @return void
356      */
357     public function save($redirect = TRUE)
358     {
359         $this->selectedLanguage = (!empty($_REQUEST['dropdown_lang'])? $_REQUEST['dropdown_lang']:$_SESSION['authenticated_user_language']);
360
361         //Clear all relevant language caches
362         $this->clearLanguageCaches();
363
364         //Retrieve changes the user is requesting and store previous values for future use.
365         $this->changedModules = $this->getChangedModules();
366
367         //Change module, appStrings, subpanels, and related links.
368         $this->changeAppStringEntries()->changeAllModuleModStrings()->renameAllRelatedLinks()->renameAllSubpanels()->renameAllDashlets();
369
370         foreach (self::$labelMap as $module=>$labelsArr) {
371             $this->renameCertainModuleModStrings($module, $labelsArr);
372         }
373
374         //Refresh the page again so module tabs are changed as the save process happens after module tabs are already generated.
375         if($redirect)
376             SugarApplication::redirect('index.php?action=wizard&module=Studio&wizard=StudioWizard&option=RenameTabs');
377     }
378
379     /**
380      * Rename all subpanels within the application.
381      *
382      *
383      * @return RenameModules
384      */
385     private function renameAllSubpanels()
386     {
387         global $beanList;
388
389         foreach($beanList as $moduleName => $beanName)
390         {
391             if( class_exists($beanName) )
392             {
393                 $this->renameModuleSubpanel($moduleName, $beanName, $this->changedModules);
394             }
395             else
396             {
397                 $GLOBALS['log']->error("Class $beanName does not exist, unable to rename.");
398             }
399         }
400
401         return $this;
402
403     }
404
405     /**
406      * Rename subpanels for a particular module.
407      *
408      * @param  string $moduleName The name of the module to be renamed
409      * @param  string $beanName  The name of the SugarBean to be renamed.
410      * @return void
411      */
412     private function renameModuleSubpanel($moduleName, $beanName)
413     {
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);
418
419         if(empty($subpanelDefs))
420         {
421             $GLOBALS['log']->debug("Found empty subpanel defs for $moduleName");
422             return;
423         }
424
425         $mod_strings = return_module_language($this->selectedLanguage, $moduleName);
426         $replacementStrings = array();
427
428         //Iterate over all subpanel entries and see if we need to make a change.
429         foreach($subpanelDefs as $subpanelName => $subpanelMetaData)
430         {
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)
434             {
435                 if( !( isset($subpanelMetaData['type']) &&  $subpanelMetaData['type'] == 'collection') //Dont bother with collections
436                     && isset($subpanelMetaData['module']) && $subpanelMetaData['module'] == $changedModuleName && isset($subpanelMetaData['title_key']) )
437                 {
438                     $replaceKey = $subpanelMetaData['title_key'];
439                     if( !isset($mod_strings[$replaceKey]) )
440                     {
441                         $GLOBALS['log']->info("No module string entry defined for: {$mod_strings[$replaceKey]}");
442                         continue;
443                     }
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);
452                     }
453                     $replacementStrings[$replaceKey] = $replacedString;
454                 }
455             }
456         }
457
458         //Now we can write out the replaced language strings for each module
459         if(count($replacementStrings) > 0)
460         {
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;
464         }
465     }
466
467     /**
468      * Retrieve the subpanel definitions for a given SugarBean object. Unforunately we can't reuse
469      * any of the SubPanelDefinion.php functions.
470      *
471      * @param  SugarBean $bean
472      * @return array The subpanel definitions.
473      */
474     private function getSubpanelDefs($bean )
475         {
476         if(empty($bean->module_dir)) {
477             return array();
478         }
479
480                 $layout_defs = array();
481
482         if ( file_exists( 'modules/' . $bean->module_dir . '/metadata/subpaneldefs.php') )
483             require('modules/' . $bean->module_dir . '/metadata/subpaneldefs.php');
484
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');
487
488          return isset($layout_defs[$bean->module_dir]['subpanel_setup']) ? $layout_defs[$bean->module_dir]['subpanel_setup'] : $layout_defs;
489         }
490
491     /**
492      * Rename all related linked within the application
493      *
494      * @return RenameModules
495      */
496     private function renameAllRelatedLinks()
497     {
498         global $beanList;
499
500         foreach($beanList as $moduleName => $beanName)
501         {
502             if( class_exists($beanName) )
503             {
504                 $this->renameModuleRelatedLinks($moduleName, $beanName);
505             }
506             else
507             {
508                 $GLOBALS['log']->fatal("Class $beanName does not exist, unable to rename.");
509             }
510         }
511
512         return $this;
513     }
514
515     /**
516      * Rename the related links within a module.
517      *
518      * @param  string $moduleName The module to be renamed
519      * @param  string $moduleClass The class name of the module to be renamed
520      * @return void
521      */
522     private function renameModuleRelatedLinks($moduleName, $moduleClass)
523     {
524         global $app_strings;
525         $GLOBALS['log']->info("Begining to renameModuleRelatedLinks for $moduleClass\n");
526         $bean = BeanFactory::getBean($moduleName);
527         if (!$bean instanceof SugarBean){
528             $GLOBALS['log']->info("Unable to get linked fields for module $moduleClass\n");
529             return;
530         }
531
532         $arrayToRename = array();
533         $replacementStrings = array();
534         $mod_strings = return_module_language($this->selectedLanguage, $moduleName);
535         $changedModules = array_keys($this->changedModules);
536
537         $relatedFields = $bean->get_related_fields();
538         foreach($relatedFields as $field => $defs)
539         {
540             if (isset($defs['module']) && in_array($defs['module'], $changedModules)){
541                 $arrayToRename[$field] = $defs;
542             }
543         }
544         $linkedFields = $bean->get_linked_fields();
545         foreach($linkedFields as $field => $defs)
546         {
547             if ($bean->load_relationship($defs['name'])){
548                 $relModule = $bean->$defs['name']->getRelatedModuleName();
549                 if (in_array($relModule, $changedModules)) {
550                     $defs['module'] = $relModule;
551                     $arrayToRename[$field] = $defs;
552                 }
553             }
554         }
555
556         foreach($arrayToRename as $link => $linkEntry)
557         {
558             $GLOBALS['log']->debug("Begining to rename for link field {$link}");
559             if( !isset($linkEntry['vname'])
560                 || (!isset($mod_strings[$linkEntry['vname']]) && !isset($app_strings[$linkEntry['vname']]))) {
561                 $GLOBALS['log']->debug("No label attribute for link $link, continuing.");
562                 continue;
563             }
564
565             $replaceKey = $linkEntry['vname'];
566             $oldStringValue = translate($replaceKey, $moduleName);
567             $renameFields = $this->changedModules[$linkEntry['module']];
568
569             if (strlen($renameFields['prev_plural']) > strlen($renameFields['prev_singular']) && strpos($oldStringValue, $renameFields['prev_plural']) !== false) {
570                 $key = 'plural';
571             } else {
572                 $key = 'singular';
573             }
574             $replacedString = str_replace(html_entity_decode_utf8($renameFields['prev_' . $key], ENT_QUOTES), $renameFields[$key], $oldStringValue);
575             $replacementStrings[$replaceKey] = $replacedString;
576         }
577
578         //Now we can write out the replaced language strings for each module
579         if(count($replacementStrings) > 0)
580         {
581             $GLOBALS['log']->debug("Writing out labels for link changes for module $moduleName, labels: " . var_export($replacementStrings,true));
582             ParserLabel::addLabels($this->selectedLanguage, $replacementStrings, $moduleName);
583             $this->renamedModules[$moduleName] = true;
584         }
585     }
586
587     /**
588      * Clear all related language cache files.
589      *
590      * @return void
591      */
592     private function clearLanguageCaches()
593     {
594         //remove the js language files
595         LanguageManager::removeJSLanguageFiles();
596
597         //remove lanugage cache files
598         LanguageManager::clearLanguageCache();
599     }
600
601     /**
602      * Rename all module strings within the application for dashlets.
603      *
604      * @return RenameModules
605      */
606     private function renameAllDashlets()
607     {
608         //Load the Dashlet metadata so we know what needs to be changed
609         if(!is_file(sugar_cached('dashlets/dashlets.php')))
610         {
611             require_once('include/Dashlets/DashletCacheBuilder.php');
612             $dc = new DashletCacheBuilder();
613             $dc->buildCache();
614         }
615
616         include(sugar_cached('dashlets/dashlets.php'));
617
618         foreach($this->changedModules as $moduleName => $replacementLabels)
619         {
620             $this->changeModuleDashletStrings($moduleName, $replacementLabels, $dashletsFiles);
621         }
622
623         return $this;
624
625     }
626
627     /*
628      * Rename the title value for all dashlets associated with a particular module
629      *
630      */
631     private function changeModuleDashletStrings($moduleName, $replacementLabels, $dashletsFiles)
632     {
633         $GLOBALS['log']->debug("Beginning to change module dashlet labels for: $moduleName ");
634         $replacementStrings = array();
635
636         foreach($dashletsFiles as $dashletName => $dashletData)
637         {
638             if( isset($dashletData['module']) && $dashletData['module'] == $moduleName && file_exists($dashletData['meta']) )
639             {
640                 require( $dashletData['meta'] );
641                 $dashletTitle = $dashletMeta[$dashletName]['title'];
642                 $currentModuleStrings = return_module_language($this->selectedLanguage, $moduleName);
643                 $modStringKey = array_search($dashletTitle,$currentModuleStrings);
644                 if($modStringKey !== FALSE)
645                 {
646                     $replacedString = str_replace(html_entity_decode_utf8($replacementLabels['prev_plural'], ENT_QUOTES), $replacementLabels['plural'], $dashletTitle);
647                     if ($replacedString == $dashletTitle) {
648                         $replacedString = str_replace(html_entity_decode_utf8($replacementLabels['prev_singular'], ENT_QUOTES), $replacementLabels['singular'], $replacedString);
649                     }
650                     $replacementStrings[$modStringKey] = $replacedString;
651                 }
652             }
653         }
654
655         //Now we can write out the replaced language strings for each module
656         if(count($replacementStrings) > 0)
657         {
658             $GLOBALS['log']->debug("Writing out labels for dashlet changes for module $moduleName, labels: " . var_export($replacementStrings,true));
659             ParserLabel::addLabels($this->selectedLanguage, $replacementStrings, $moduleName);
660         }
661     }
662
663
664     /**
665      * Rename all module strings within the application.
666      *
667      * @return RenameModules
668      */
669     private function changeAllModuleModStrings()
670     {
671         foreach($this->changedModules as $moduleName => $replacementLabels)
672         {
673             $this->changeModuleModStrings($moduleName, $replacementLabels);
674         }
675
676         return $this;
677     }
678
679     /**
680       * Rename all module strings within the leads module.
681       *
682       * @param  string $targetModule The name of the module that owns the labels to be changed.
683       * @param  array $labelKeysToReplace The labels to be changed.
684       * @return RenameModules
685       */
686      private function renameCertainModuleModStrings($targetModule, $labelKeysToReplace)
687      {
688          $GLOBALS['log']->debug("Beginning to rename labels for $targetModule module");
689          foreach($this->changedModules as $moduleName => $replacementLabels)
690          {
691              $this->changeCertainModuleModStrings($moduleName, $replacementLabels, $targetModule, $labelKeysToReplace);
692          }
693
694          return $this;
695      }
696
697     /**
698      * For a particular module, rename any relevant module strings that need to be replaced.
699      *
700      * @param  string $moduleName The name of the module to be renamed.
701      * @param  $replacementLabels
702      * @param  string $targetModule The name of the module that owns the labels to be changed.
703      * @param  array $labelKeysToReplace The labels to be changed.
704      * @return void
705      */
706     private function changeCertainModuleModStrings($moduleName, $replacementLabels, $targetModule, $labelKeysToReplace)
707     {
708         $GLOBALS['log']->debug("Beginning to change module labels for : $moduleName");
709         $currentModuleStrings = return_module_language($this->selectedLanguage, $targetModule);
710
711         $replacedLabels = array();
712         foreach($labelKeysToReplace as $entry)
713         {
714             if (!isset($entry['source']) || $entry['source'] != $moduleName) {
715                 // skip this entry if the source module does not match the module being renamed
716                 continue;
717             }
718
719             $formattedLanguageKey = $this->formatModuleLanguageKey($entry['name'], $replacementLabels);
720
721             //If the static of dynamic key exists it should be replaced.
722             if( isset($currentModuleStrings[$formattedLanguageKey]) )
723             {
724                 $oldStringValue = $currentModuleStrings[$formattedLanguageKey];
725                 $newStringValue = $this->replaceSingleLabel($oldStringValue, $replacementLabels, $entry);
726                 if ($oldStringValue != $newStringValue) {
727                     $replacedLabels[$formattedLanguageKey] = $newStringValue;
728                 }
729             }
730         }
731
732         //Save all entries
733         ParserLabel::addLabels($this->selectedLanguage, $replacedLabels, $targetModule);
734         $this->renamedModules[$targetModule] = true;
735     }
736
737
738     /**
739      * For a particular module, rename any relevant module strings that need to be replaced.
740      *
741      * @param  string $moduleName The name of the module to be renamed.
742      * @param  $replacementLabels
743      * @return void
744      */
745     private function changeModuleModStrings($moduleName, $replacementLabels)
746     {
747         $GLOBALS['log']->info("Begining to change module labels for: $moduleName");
748         $currentModuleStrings = return_module_language($this->selectedLanguage, $moduleName);
749         $labelKeysToReplace = array(
750             array('name' => 'LNK_NEW_RECORD', 'type' => 'plural'), //Module built modules, Create <moduleName>
751             array('name' => 'LNK_LIST', 'type' => 'plural'), //Module built modules, View <moduleName>
752             array('name' => 'LNK_NEW_###MODULE_SINGULAR###', 'type' => 'singular'),
753             array('name' => 'LNK_###MODULE_SINGULAR###_LIST', 'type' => 'plural'),
754             array('name' => 'LNK_###MODULE_SINGULAR###_REPORTS', 'type' => 'singular'),
755             array('name' => 'LNK_IMPORT_VCARD', 'type' => 'singular'),
756             array('name' => 'LNK_IMPORT_###MODULE_PLURAL###', 'type' => 'plural'),
757             array('name' => 'MSG_SHOW_DUPLICATES', 'type' => 'singular', 'case' => 'both'),
758             array('name' => 'LBL_SAVE_###MODULE_SINGULAR###', 'type' => 'singular'),
759             array('name' => 'LBL_LIST_FORM_TITLE', 'type' => 'singular'), //Popup title
760             array('name' => 'LBL_SEARCH_FORM_TITLE', 'type' => 'singular'), //Popup title
761         );
762
763         $replacedLabels = array();
764         foreach($labelKeysToReplace as $entry)
765         {
766             $formattedLanguageKey = $this->formatModuleLanguageKey($entry['name'], $replacementLabels);
767
768             //If the static of dynamic key exists it should be replaced.
769             if( isset($currentModuleStrings[$formattedLanguageKey]) )
770             {
771                 $oldStringValue = $currentModuleStrings[$formattedLanguageKey];
772                 $replacedLabels[$formattedLanguageKey] = $this->replaceSingleLabel($oldStringValue, $replacementLabels, $entry);
773                 if( isset($entry['case']) && $entry['case'] == 'both')
774                 {
775                     $replacedLabels[$formattedLanguageKey] = $this->replaceSingleLabel($replacedLabels[$formattedLanguageKey], $replacementLabels, $entry, 'strtolower');
776                 }
777             }
778         }
779
780         //Save all entries
781         ParserLabel::addLabels($this->selectedLanguage, $replacedLabels, $moduleName);
782         $this->renamedModules[$moduleName] = true;
783     }
784
785     /**
786      * Format our dynamic keys containing module strings to a valid key depending on the module.
787      *
788      * @param  string $unformatedKey
789      * @param  string $replacementStrings
790      * @return string
791      */
792     private function formatModuleLanguageKey($unformatedKey, $replacementStrings)
793     {
794         $unformatedKey = str_replace('###MODULE_SINGULAR###', strtoupper($replacementStrings['key_singular']), $unformatedKey);
795         return str_replace('###MODULE_PLURAL###', strtoupper($replacementStrings['key_plural']), $unformatedKey);
796
797     }
798
799     /**
800      * Replace a label with a new value based on metadata which specifies the label as either singular or plural.
801      *
802      * @param  string $oldStringValue
803      * @param  string $replacementLabels
804      * @param  array $replacementMetaData
805      * @return string
806      */
807     private function replaceSingleLabel($oldStringValue, $replacementLabels, $replacementMetaData, $modifier = '')
808     {
809         $replaceKey = 'prev_' . $replacementMetaData['type'];
810         $search = html_entity_decode_utf8($replacementLabels[$replaceKey], ENT_QUOTES);
811         $replace = $replacementLabels[$replacementMetaData['type']];
812         if( !empty($modifier) )
813         {
814             $search = call_user_func($modifier, $search);
815             $replace = call_user_func($modifier, $replace);
816         }
817         
818         // Bug 47957
819         // If nothing was replaced - try to replace original string
820         $result = '';
821         $replaceCount = 0;
822         $result = str_replace($search, $replace, $oldStringValue, $replaceCount);
823         if(!$replaceCount){
824             $replaceKey = 'key_' . $replacementMetaData['type'];
825             $search = html_entity_decode_utf8($replacementLabels[$replaceKey], ENT_QUOTES);
826             $result = str_replace($search, $replace, $oldStringValue, $replaceCount);
827         }
828         return $result;
829     }
830
831
832     /**
833      * Save changes to the module names to the app string entries for both the moduleList and moduleListSingular entries.
834      *
835      * @return RenameModules
836      */
837     private function changeAppStringEntries()
838     {
839         $GLOBALS['log']->debug('Begining to save app string entries');
840         //Save changes to the moduleList app string entry
841         DropDownHelper::saveDropDown($_REQUEST);
842
843         //Save changes to the moduleListSingular app string entry
844         $newParams = array();
845         $newParams['dropdown_name'] = 'moduleListSingular';
846         $newParams['dropdown_lang'] = isset($_REQUEST['dropdown_lang']) ? $_REQUEST['dropdown_lang'] : '';
847         $newParams['use_push'] = true;
848         DropDownHelper::saveDropDown($this->createModuleListSingularPackage($newParams, $this->changedModules));
849
850         //Save changes to the "*type_display*" app_list_strings entry.
851         global $app_list_strings;
852         
853         $typeDisplayList = getTypeDisplayList();
854         
855         foreach (array_keys($this->changedModules)as $moduleName) 
856         {
857             foreach($typeDisplayList as $typeDisplay)
858             {
859                 if(isset($app_list_strings[$typeDisplay]) && isset($app_list_strings[$typeDisplay][$moduleName]))
860                 {
861                     $newParams['dropdown_name'] = $typeDisplay;
862                     DropDownHelper::saveDropDown($this->createModuleListSingularPackage($newParams, array($moduleName => $this->changedModules[$moduleName])));
863                  }
864             }
865         }
866         return $this;
867     }
868
869     /**
870      * Create an array entry that can be passed to the DropDownHelper:saveDropDown function so we can re-utilize
871      * the save logic.
872      *
873      * @param  array $params
874      * @param  array $changedModules
875      * @return
876      */
877     private function createModuleListSingularPackage($params, $changedModules)
878     {
879         $count = 0;
880         foreach($changedModules as $moduleName => $package)
881         {
882             $singularString = $package['singular'];
883
884             $params['slot_' . $count] = $count;
885             $params['key_' . $count] = $moduleName;
886             $params['value_' . $count] = $singularString;
887             $params['delete_' . $count] = '';
888
889             $count++;
890         }
891
892         return $params;
893
894     }
895
896     /**
897      * Determine which modules have been updated and return an array with the module name as the key
898      * and the singular/plural entries as the value.
899      *
900      * @return array
901      */
902     private function getChangedModules()
903     {
904         $count = 0;
905         $allModuleEntries = array();
906         $results = array();
907         $params = $_REQUEST;
908
909         $selected_lang = (!empty($params['dropdown_lang'])?$params['dropdown_lang']:$_SESSION['authenticated_user_language']);
910         $current_app_list_string = return_app_list_strings_language($selected_lang);
911
912         while(isset($params['slot_' . $count]))
913         {
914             $index = $params['slot_' . $count];
915
916             $key = (isset($params['key_' . $index]))?SugarCleaner::stripTags($params['key_' . $index]): 'BLANK';
917             $value = (isset($params['value_' . $index]))?SugarCleaner::stripTags($params['value_' . $index]): '';
918             $svalue = (isset($params['svalue_' . $index]))?SugarCleaner::stripTags($params['svalue_' . $index]): $value;
919             if($key == 'BLANK')
920                $key = '';
921
922             $key = trim($key);
923             $value = trim($value);
924             $svalue = trim($svalue);
925
926             //If the module key dne then do not continue with this rename.
927             if( isset($current_app_list_string['moduleList'][$key]) )
928                 $allModuleEntries[$key] = array('s' => $svalue, 'p' => $value);
929             else
930                 $_REQUEST['delete_' . $count] = TRUE;
931
932
933            $count++;
934         }
935
936
937         foreach($allModuleEntries as $k => $e)
938         {
939             $svalue = $e['s'];
940             $pvalue = $e['p'];
941             $prev_plural = $current_app_list_string['moduleList'][$k];
942             $prev_singular = isset($current_app_list_string['moduleListSingular'][$k]) ? $current_app_list_string['moduleListSingular'][$k] : $prev_plural;
943             if( strcmp($prev_plural, $pvalue) != 0 || (strcmp($prev_singular, $svalue) != 0) )
944             {
945                 $results[$k] = array('singular' => $svalue, 'plural' => $pvalue, 'prev_singular' => $prev_singular, 'prev_plural' => $prev_plural,
946                                      'key_plural' => $k, 'key_singular' => $this->getModuleSingularKey($k)
947                 );
948             }
949
950         }
951
952         return $results;
953     }
954
955
956     /**
957      * Return the 'singular' name of a module (Eg. Opportunity for Opportunities) given a moduleName which is a key
958      * in the app string moduleList array.  If no entry is found, simply return the moduleName as this is consistant with modules
959      * built by moduleBuilder.
960      *
961      * @param  string $moduleName
962      * @return string The 'singular' name of a module.
963      */
964     private function getModuleSingularKey($moduleName)
965     {
966         $className = isset($GLOBALS['beanList'][$moduleName]) ? $GLOBALS['beanList'][$moduleName] : null;
967         if( is_null($className) || ! class_exists($className) )
968         {
969             $GLOBALS['log']->error("Unable to get module singular key for class: $className");
970             return $moduleName;
971         }
972
973         $tmp = new $className();
974         if( property_exists($tmp, 'object_name') )
975             return $tmp->object_name;
976         else
977             return $moduleName;
978     }
979
980     /**
981      * Return an array of the modules whos mod_strings have been modified.
982      *
983      * @return array
984      */
985     public function getRenamedModules()
986     {
987         return $this->renamedModules;
988     }
989 }
990
991
992