]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - ModuleInstall/ModuleInstaller.php
Release 6.2.3
[Github/sugarcrm.git] / ModuleInstall / ModuleInstaller.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-2011 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 /*
40  * ModuleInstaller - takes an installation package from files in the custom/Extension/X directories, and moves them into custom/X to install them.
41  * If a directory has multiple files they are concatenated together.
42  * Relevant directories (X) are Layoutdefs, Vardefs, Include (bean stuff), Language, TableDictionary (relationships)
43  *
44  * Installation steps that involve more than just copying files:
45  * 1. installing custom fields - calls bean->custom_fields->addField
46  * 2. installing relationships - calls createTableParams to build the relationship table, and createRelationshipMeta to add the relationship to the relationship table
47  * 3. rebuilding the relationships - at almost the last step in install(), calls modules/Administration/RebuildRelationship.php
48  * 4. repair indices - uses "modules/Administration/RepairIndex.php";
49  */
50
51
52
53 require_once('include/utils/progress_bar_utils.php');
54
55 require_once('ModuleInstall/ModuleScanner.php');
56 define('DISABLED_PATH', 'Disabled');
57
58 class ModuleInstaller{
59         var $modules = array();
60         var $silent = false;
61         var $base_dir  = '';
62         var $modulesInPackage = array();
63
64         function ModuleInstaller(){
65                 $this->ms = new ModuleScanner();
66                 $this->modules = get_module_dir_list();
67                 $this->db = & DBManagerFactory::getInstance();
68
69         }
70
71    /*
72     * ModuleInstaller->install includes the manifest.php from the base directory it has been given. If it has been asked to do an upgrade it checks to see if there is
73     * an upgrade_manifest defined in the manifest; if not it errors. It then adds the bean into the custom/Extension/application/Ext/Include/<module>.php - sets beanList, beanFiles
74     * and moduleList - and then calls ModuleInstaller->merge_files('Ext/Include', 'modules.ext.php', '', true) to merge the individual module files into a combined file
75     * /custom/Extension/application/Ext/Include/modules.ext.php (which now contains a list of all $beanList, $beanFiles and $moduleList for all extension modules) -
76     * this file modules.ext.php is included at the end of modules.php.
77     *
78     * Finally it runs over a list of defined tasks; then install_beans, then install_custom_fields, then clear the Vardefs, run a RepairAndClear, then finally call rebuild_relationships.
79     */
80         function install($base_dir, $is_upgrade = false, $previous_version = ''){
81                 if(defined('TEMPLATE_URL'))SugarTemplateUtilities::disableCache();
82                 if(!empty($GLOBALS['sugar_config']['moduleInstaller']['packageScan'])){
83                         $this->ms->scanPackage($base_dir);
84                         if($this->ms->hasIssues()){
85                                 $this->ms->displayIssues();
86                                 sugar_cleanup(true);
87                         }
88                 }
89
90                 global $app_strings, $mod_strings;
91                 $this->base_dir = $base_dir;
92                 $total_steps = 5; //minimum number of steps with no tasks
93                 $current_step = 0;
94                 $tasks = array(
95                         'pre_execute',
96                         'install_copy',
97                         'install_images',
98                         'install_menus',
99                         'install_dcactions',
100                         'install_userpage',
101                         'install_dashlets',
102                         'install_administration',
103                         'install_connectors',
104                         'install_vardefs',
105                         'install_layoutdefs',
106                         'install_layoutfields',
107                         'install_relationships',
108                         'install_languages',
109             'install_logichooks',
110                         'post_execute',
111                         'reset_opcodes',
112                 );
113
114                 $total_steps += count($tasks);
115                 if(file_exists($this->base_dir . '/manifest.php')){
116                                 if(!$this->silent){
117                                         $current_step++;
118                                         display_progress_bar('install', $current_step, $total_steps);
119                                         echo '<div id ="displayLoglink" ><a href="#" onclick="document.getElementById(\'displayLog\').style.display=\'\'">'
120                                                 .$app_strings['LBL_DISPLAY_LOG'].'</a> </div><div id="displayLog" style="display:none">';
121                                 }
122
123                                 include($this->base_dir . '/manifest.php');
124                                 if($is_upgrade && !empty($previous_version)){
125                                         //check if the upgrade path exists
126                                         if(!empty($upgrade_manifest)){
127                                                 if(!empty($upgrade_manifest['upgrade_paths'])){
128                                                         if(!empty($upgrade_manifest['upgrade_paths'][$previous_version])){
129                                                                 $installdefs =  $upgrade_manifest['upgrade_paths'][$previous_version];
130                                                         }else{
131                                                                 $errors[] = 'No Upgrade Path Found in manifest.';
132                                                                 $this->abort($errors);
133                                                         }//fi
134                                                 }//fi
135                                         }//fi
136                                 }//fi
137                                 $this->id_name = $installdefs['id'];
138                                 $this->installdefs = $installdefs;
139                                 $installed_modules = array();
140                                 $tab_modules = array();
141                                 if(isset($installdefs['beans'])){
142                                         $str = "<?php \n //WARNING: The contents of this file are auto-generated\n";
143                                         foreach($installdefs['beans'] as $bean){
144                                                 if(!empty($bean['module']) && !empty($bean['class']) && !empty($bean['path'])){
145                                                         $module = $bean['module'];
146                                                         $class = $bean['class'];
147                                                         $path = $bean['path'];
148
149                                                         $str .= "\$beanList['$module'] = '$class';\n";
150                                                         $str .= "\$beanFiles['$class'] = '$path';\n";
151                                                         if($bean['tab']){
152                                                                 $str .= "\$moduleList[] = '$module';\n";
153                                                                 $this->install_user_prefs($module, empty($bean['hide_by_default']));
154                                                                 $tab_modules[] = $module;
155                                                         }else{
156                                                                 $str .= "\$modules_exempt_from_availability_check['$module'] = '$module';\n";
157                                                                 $str .= "\$modInvisList[] = '$module';\n";
158                                                         }
159                                                         $installed_modules[] = $module;
160                                                 }else{
161                                                         $errors[] = 'Bean array not well defined.';
162                                                         $this->abort($errors);
163                                                 }
164                                         }
165                                         $str.= "\n?>";
166                                         if(!file_exists("custom/Extension/application/Ext/Include")){
167                                                 mkdir_recursive("custom/Extension/application/Ext/Include", true);
168                                         }
169                                         $out = sugar_fopen("custom/Extension/application/Ext/Include/$this->id_name.php", 'w');
170                                         fwrite($out,$str);
171                                         fclose($out);
172                                         $this->rebuild_modules();
173                                 }
174                                 if(!$this->silent){
175                                         $current_step++;
176                                         update_progress_bar('install', $current_step, $total_steps);
177                                 }
178
179                                 foreach($tasks as $task){
180                                         $this->$task();
181                                         if(!$this->silent){
182                                                 $current_step++;
183                                                 update_progress_bar('install', $current_step, $total_steps);
184                                         }
185                                 }
186                                 $this->install_beans($installed_modules);
187                                 if(!$this->silent){
188                                         $current_step++;
189                                         update_progress_bar('install', $total_steps, $total_steps);
190                                 }
191                                 if(isset($installdefs['custom_fields'])){
192                                         $this->log(translate('LBL_MI_IN_CUSTOMFIELD'));
193                                         $this->install_custom_fields($installdefs['custom_fields']);
194                                 }
195                                 if(!$this->silent){
196                                         $current_step++;
197                                         update_progress_bar('install', $current_step, $total_steps);
198                                         echo '</div>';
199                                 }
200                                 if(!$this->silent){
201                                         $current_step++;
202                                         update_progress_bar('install', $current_step, $total_steps);
203                                         echo '</div>';
204                                 }
205                                 $selectedActions = array(
206                         'clearTpls',
207                         'clearJsFiles',
208                         'clearDashlets',
209                         'clearVardefs',
210                         'clearJsLangFiles',
211                         'rebuildAuditTables',
212                         'repairDatabase',
213                 );
214                                 VardefManager::clearVardef();
215                                 global $beanList, $beanFiles, $moduleList;
216                                 if (file_exists('custom/application/Ext/Include/modules.ext.php'))
217                                 {
218                                     include('custom/application/Ext/Include/modules.ext.php');
219                                 }
220                                 require_once("modules/Administration/upgrade_custom_relationships.php");
221                 upgrade_custom_relationships($installed_modules);
222                                 $this->rebuild_all(true);
223                                 require_once('modules/Administration/QuickRepairAndRebuild.php');
224                                 $rac = new RepairAndClear();
225                                 $rac->repairAndClearAll($selectedActions, $installed_modules,true, false);
226                                 $this->rebuild_relationships();
227                                 UpdateSystemTabs('Add',$tab_modules);
228                                 
229                                 //clear the unified_search_module.php file 
230                     require_once('modules/Home/UnifiedSearchAdvanced.php');
231                     UnifiedSearchAdvanced::unlinkUnifiedSearchModulesFile(); 
232                                                 
233                                 $this->log('<br><b>' . translate('LBL_MI_COMPLETE') . '</b>');
234                 }else{
235                         die("No \$installdefs Defined In $this->base_dir/manifest.php");
236                 }
237
238         }
239
240         function install_user_prefs($module, $hide_from_user=false){
241                 UserPreference::updateAllUserPrefs('display_tabs', $module, '', true, !$hide_from_user);
242                 UserPreference::updateAllUserPrefs('hide_tabs', $module, '', true, $hide_from_user);
243                 UserPreference::updateAllUserPrefs('remove_tabs', $module, '', true, $hide_from_user);
244         }
245         function uninstall_user_prefs($module){
246                 UserPreference::updateAllUserPrefs('display_tabs', $module, '', true, true);
247                 UserPreference::updateAllUserPrefs('hide_tabs', $module, '', true, true);
248                 UserPreference::updateAllUserPrefs('remove_tabs', $module, '', true, true);
249         }
250
251         function pre_execute(){
252                 require_once($this->base_dir . '/manifest.php');
253                 if(isset($this->installdefs['pre_execute']) && is_array($this->installdefs['pre_execute'])){
254                         foreach($this->installdefs['pre_execute'] as $includefile){
255                                 require_once(str_replace('<basepath>', $this->base_dir, $includefile));
256                         }
257                 }
258         }
259
260         function post_execute(){
261                 require_once($this->base_dir . '/manifest.php');
262                 if(isset($this->installdefs['post_execute']) && is_array($this->installdefs['post_execute'])){
263                         foreach($this->installdefs['post_execute'] as $includefile){
264                                 require_once(str_replace('<basepath>', $this->base_dir, $includefile));
265                         }
266                 }
267         }
268
269         function pre_uninstall(){
270                 require_once($this->base_dir . '/manifest.php');
271                 if(isset($this->installdefs['pre_uninstall']) && is_array($this->installdefs['pre_uninstall'])){
272                         foreach($this->installdefs['pre_uninstall'] as $includefile){
273                                 require_once(str_replace('<basepath>', $this->base_dir, $includefile));
274                         }
275                 }
276         }
277
278         function post_uninstall(){
279                 require_once($this->base_dir . '/manifest.php');
280                 if(isset($this->installdefs['post_uninstall']) && is_array($this->installdefs['post_uninstall'])){
281                         foreach($this->installdefs['post_uninstall'] as $includefile){
282                                 require_once(str_replace('<basepath>', $this->base_dir, $includefile));
283                         }
284                 }
285         }
286
287         /*
288      * ModuleInstaller->install_copy gets the copy section of installdefs in the manifest and calls copy_path to copy each path (file or directory) to its final location
289      * (specified as from and to in the manifest), replacing <basepath> by the base_dir value passed in to install.
290      */
291         function install_copy(){
292                 if(isset($this->installdefs['copy'])){
293                         /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:11 PM */
294                         $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore" );
295                         /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
296                         foreach($this->installdefs['copy'] as $cp){
297                                 $GLOBALS['log']->debug("Copying ..." . $cp['from'].  " to " .$cp['to'] );
298                                 /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:11 PM */
299                                 //$this->copy_path($cp['from'], $cp['to']);
300                                 $this->copy_path($cp['from'], $cp['to'], $backup_path);
301                                 /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
302                         }
303                         //here we should get the module list again as we could have copied something to the modules dir
304                         $this->modules = get_module_dir_list();
305                 }
306         }
307         function uninstall_copy(){
308                 if(!empty($this->installdefs['copy'])){
309                                         foreach($this->installdefs['copy'] as $cp){
310                                                 $cp['to'] = clean_path(str_replace('<basepath>', $this->base_dir, $cp['to']));
311                                                 $cp['from'] = clean_path(str_replace('<basepath>', $this->base_dir, $cp['from']));
312                                                 $GLOBALS['log']->debug('Unlink ' . $cp['to']);
313                                 /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:11 PM */
314                                                 //rmdir_recursive($cp['to']);
315
316                                                 $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore/".$cp['to'] );
317                                                 $this->uninstall_new_files($cp, $backup_path);
318                                                 $this->copy_path($backup_path, $cp['to'], $backup_path, true);
319                                 /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
320                                         }
321                                         $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore");
322                                         if(file_exists($backup_path))
323                                                 rmdir_recursive($backup_path);
324                                 }
325         }
326
327
328         /**
329          * Removes any files that were added by the loaded module. If the files already existed prior to install
330          * it will be handled by copy_path with the uninstall parameter.
331          *
332          */
333         function uninstall_new_files($cp, $backup_path){
334                 $zip_files = $this->dir_get_files($cp['from'],$cp['from']);
335                 $backup_files = $this->dir_get_files($backup_path, $backup_path);
336                 foreach($zip_files as $k=>$v){
337                         //if it's not a backup then it is probably a new file but we'll check that it is not in the md5.files first
338                         if(!isset($backup_files[$k])){
339                                 $to = $cp['to'] . $k;
340                                 //if it's not a sugar file then we remove it otherwise we can't restor it
341                                 if(!$this->ms->sugarFileExists($to)){
342                                         $GLOBALS['log']->debug('ModuleInstaller[uninstall_new_file] deleting file ' . $to);
343                                         if(file_exists($to)) {
344                                             unlink($to);
345                                         }
346                                 }else{
347                                         $GLOBALS['log']->fatal('ModuleInstaller[uninstall_new_file] Could not remove file ' . $to . ' as no backup file was found to restore to');
348                                 }
349                         }
350                 }
351                 //lets check if the directory is empty if it is we will delete it as well
352                 $files_remaining = $this->dir_file_count($cp['to']);
353                 if(file_exists($cp['to']) && $files_remaining == 0){
354                         $GLOBALS['log']->debug('ModuleInstaller[uninstall_new_file] deleting directory ' . $cp['to']);
355                         rmdir_recursive($cp['to']);
356                 }
357
358         }
359
360
361         function install_dashlets(){
362         if(isset($this->installdefs['dashlets'])){
363                         foreach($this->installdefs['dashlets'] as $cp){
364                                 $this->log(translate('LBL_MI_IN_DASHLETS') . $cp['name']);
365                                 $cp['from'] = str_replace('<basepath>', $this->base_dir, $cp['from']);
366                                 $path = 'custom/modules/Home/Dashlets/' . $cp['name'] . '/';
367                                 $GLOBALS['log']->debug("Installing Dashlet " . $cp['name'] . "..." . $cp['from'] );
368                                 if(!file_exists($path)){
369                                         mkdir_recursive($path, true);
370                                 }
371                                 copy_recursive($cp['from'] , $path);
372                         }
373                         include('modules/Administration/RebuildDashlets.php');
374
375                 }
376         }
377
378         function uninstall_dashlets(){
379         if(isset($this->installdefs['dashlets'])){
380                         foreach($this->installdefs['dashlets'] as $cp){
381                                 $this->log(translate('LBL_MI_UN_DASHLETS') . $cp['name']);
382                                 $path = 'custom/modules/Home/Dashlets/' . $cp['name'];
383                                 $GLOBALS['log']->debug('Unlink ' .$path);
384                                 if (file_exists($path))
385                                         rmdir_recursive($path);
386                         }
387                         include('modules/Administration/RebuildDashlets.php');
388                 }
389         }
390
391
392         function install_images(){
393         if(isset($this->installdefs['image_dir'])){
394                         $this->log( translate('LBL_MI_IN_IMAGES') );
395                         $this->copy_path($this->installdefs['image_dir'] , 'custom/themes');
396
397                 }
398         }
399
400         function install_menus(){
401         if(isset($this->installdefs['menu'])){
402                         $this->log(translate('LBL_MI_IN_MENUS'));
403                         foreach($this->installdefs['menu'] as $menu){
404                                 $menu['from'] = str_replace('<basepath>', $this->base_dir, $menu['from']);
405                                 $GLOBALS['log']->debug("Installing Menu ..." . $menu['from'].  " for " .$menu['to_module'] );
406                                 $path = 'custom/Extension/modules/' . $menu['to_module']. '/Ext/Menus';
407                                 if($menu['to_module'] == 'application'){
408                                         $path ='custom/Extension/' . $menu['to_module']. '/Ext/Menus';
409                                 }
410                                 if(!file_exists($path)){
411                                         mkdir_recursive($path, true);
412
413                                 }
414                                 copy_recursive($menu['from'] , $path . '/'. $this->id_name . '.php');
415                         }
416                         $this->rebuild_menus();
417                 }
418         }
419
420         function uninstall_menus(){
421         if(isset($this->installdefs['menu'])){
422                         $this->log(translate('LBL_MI_UN_MENUS'));
423                         foreach($this->installdefs['menu'] as $menu){
424                                 $menu['from'] = str_replace('<basepath>', $this->base_dir, $menu['from']);
425                                 $GLOBALS['log']->debug("Uninstalling Menu ..." . $menu['from'].  " for " .$menu['to_module'] );
426                                 $path = 'custom/Extension/modules/' . $menu['to_module']. '/Ext/Menus';
427                                 if($menu['to_module'] == 'application'){
428                                         $path ='custom/Extension/' . $menu['to_module']. '/Ext/Menus';
429                                 }
430                                 if (sugar_is_file($path . '/'. $this->id_name . '.php', 'w'))
431                                 {
432                                         rmdir_recursive( $path . '/'. $this->id_name . '.php');
433                                 }
434                                 else if (sugar_is_file($path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php', 'w'))
435                                 {
436                                         rmdir_recursive( $path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php');
437                                 }
438                         }
439                         $this->rebuild_menus();
440                 }
441         }
442
443         function install_dcactions(){
444                 if(isset($this->installdefs['dcaction'])){
445                         $this->log(translate('LBL_MI_IN_MENUS'));
446                         foreach($this->installdefs['dcaction'] as $action){
447                                 $action['from'] = str_replace('<basepath>', $this->base_dir, $action['from']);
448                                 $GLOBALS['log']->debug("Installing DCActions ..." . $action['from']);
449                                 $path = 'custom/Extension/application/Ext/DashletContainer/Containers';
450                                 if(!file_exists($path)){
451                                         mkdir_recursive($path, true);
452                                 }
453                                 copy_recursive($action['from'] , $path . '/'. $this->id_name . '.php');
454                         }
455                         $this->rebuild_dashletcontainers();
456                 }
457         }
458
459         function uninstall_dcactions(){
460         if(isset($this->installdefs['dcaction'])){
461                         $this->log(translate('LBL_MI_UN_MENUS'));
462                         foreach($this->installdefs['dcaction'] as $action){
463                                 $action['from'] = str_replace('<basepath>', $this->base_dir, $action['from']);
464                                 $GLOBALS['log']->debug("Uninstalling DCActions ..." . $action['from'] );
465                                 $path = 'custom/Extension/application/Ext/DashletContainer/Containers';
466                                 if (sugar_is_file($path . '/'. $this->id_name . '.php', 'w'))
467                                 {
468                                         rmdir_recursive( $path . '/'. $this->id_name . '.php');
469                                 }
470                                 else if (sugar_is_file($path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php', 'w'))
471                                 {
472                                         rmdir_recursive( $path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php');
473                                 }
474                         }
475                         $this->rebuild_dashletcontainers();
476                 }
477         }
478
479         function install_administration(){
480         if(isset($this->installdefs['administration'])){
481                         $this->log(translate('LBL_MI_IN_ADMIN'));
482                         foreach($this->installdefs['administration'] as $administration){
483                                 $administration['from'] = str_replace('<basepath>', $this->base_dir, $administration['from']);
484                                 $GLOBALS['log']->debug("Installing Administration Section ..." . $administration['from'] );
485                                 $path = 'custom/Extension/modules/Administration/Ext/Administration';
486                                 if(!file_exists($path)){
487                                         mkdir_recursive($path, true);
488
489                                 }
490                                 copy_recursive($administration['from'] , $path . '/'. $this->id_name . '.php');
491                         }
492                         $this->rebuild_administration();
493                 }
494
495         }
496         function uninstall_administration(){
497         if(isset($this->installdefs['administration'])){
498                         $this->log(translate('LBL_MI_UN_ADMIN'));
499                         foreach($this->installdefs['administration'] as $administration){
500                                 $administration['from'] = str_replace('<basepath>', $this->base_dir, $administration['from']);
501                                 $GLOBALS['log']->debug("Uninstalling Administration Section ..." . $administration['from'] );
502                                 $path = 'custom/Extension/modules/Administration/Ext/Administration';
503                                 if (sugar_is_file($path . '/'. $this->id_name . '.php', "w"))
504                                         rmdir_recursive( $path . '/'. $this->id_name . '.php');
505                                 else if (sugar_is_file($path . '/'. DISABLED_PATH . "/" . $this->id_name . '.php', "w"))
506                                         rmdir_recursive( $path . '/'. DISABLED_PATH . "/" . $this->id_name . '.php');
507                         }
508                         $this->rebuild_administration();
509                 }
510         }
511
512         function install_connectors(){
513         if(isset($this->installdefs['connectors'])){
514                 foreach($this->installdefs['connectors'] as $cp){
515                                 $this->log(translate('LBL_MI_IN_CONNECTORS') . $cp['name']);
516                                 $dir = str_replace('_','/',$cp['name']);
517                                 $cp['connector'] = str_replace('<basepath>', $this->base_dir, $cp['connector']);
518                                 $source_path = 'custom/modules/Connectors/connectors/sources/' . $dir. '/';
519                                 $GLOBALS['log']->debug("Installing Connector " . $cp['name'] . "..." . $cp['connector'] );
520                                 if(!file_exists($source_path)){
521                                         mkdir_recursive($source_path, true);
522                                 }
523                                 copy_recursive($cp['connector'] , $source_path);
524
525                                 //Install optional formatter code if it is specified
526                                 if(!empty($cp['formatter'])) {
527                                         $cp['formatter'] = str_replace('<basepath>', $this->base_dir, $cp['formatter']);
528                                         $formatter_path = 'custom/modules/Connectors/connectors/formatters/' . $dir. '/';
529                                         if(!file_exists($formatter_path)){
530                                                 mkdir_recursive($formatter_path, true);
531                                         }
532                                         copy_recursive($cp['formatter'] , $formatter_path);
533                                 }
534                         }
535                         require_once('include/connectors/utils/ConnectorUtils.php');
536                         ConnectorUtils::installSource($cp['name']);
537                 }
538
539         }
540         function uninstall_connectors(){
541         if(isset($this->installdefs['connectors'])){
542                 foreach($this->installdefs['connectors'] as $cp){
543                                 $this->log(translate('LBL_MI_UN_CONNECTORS') . $cp['name']);
544                                 $dir = str_replace('_','/',$cp['name']);
545                                 $source_path = 'custom/modules/Connectors/connectors/sources/' . $dir;
546                                 $formatter_path = 'custom/modules/Connectors/connectors/formatters/' . $dir;
547                                 $GLOBALS['log']->debug('Unlink ' .$source_path);
548                                 rmdir_recursive($source_path);
549                                 rmdir_recursive($formatter_path);
550                         }
551                         require_once('include/connectors/utils/ConnectorUtils.php');
552                         //ConnectorUtils::getConnectors(true);
553                         ConnectorUtils::uninstallSource($cp['name']);
554                 }
555         }
556
557         function install_userpage(){
558         if(isset($this->installdefs['user_page'])){
559                                         $this->log(translate('LBL_MI_IN_USER'));
560                                         foreach($this->installdefs['user_page'] as $userpage){
561                                                 $userpage['from'] = str_replace('<basepath>', $this->base_dir, $userpage['from']);
562                                                 $GLOBALS['log']->debug("Installing User Page Section ..." . $userpage['from'] );
563                                                 $path = 'custom/Extension/modules/Users/Ext/UserPage';
564                                                 if(!file_exists($path)){
565                                                         mkdir_recursive($path, true);
566
567                                                 }
568                                                 copy_recursive($userpage['from'] , $path . '/'. $this->id_name . '.php');
569                                         }
570                                         $this->rebuild_userpage();
571                                 }
572
573         }
574         function uninstall_userpage(){
575             if(isset($this->installdefs['user_page'])){
576                                         $this->log(translate('LBL_MI_UN_USER') );
577                                         foreach($this->installdefs['user_page'] as $userpage){
578                                                 $userpage['from'] = str_replace('<basepath>', $this->base_dir, $userpage['from']);
579                                                 $GLOBALS['log']->debug("Uninstalling User Page Section ..." . $userpage['from'] );
580                                                 $path = 'custom/Extension/modules/Users/Ext/UserPage';
581                                                 rmdir_recursive( $path . '/'. $this->id_name . '.php');
582                                         }
583                                         $this->rebuild_userpage();
584                                 }
585         }
586
587     /*
588      * ModuleInstaller->install_vardefs uses the vardefs section of the installdefs and copies from the 'from' path (replacing <basepath> as usual) to either
589      * custom/Extension/modules/<module>/Ext/Vardefs or custom/Extension/<module>/Ext/Vardefs if the 'to_module' value in the installdefs is set to 'application'.
590      * Finally rebuild_vardefs() is used to merge /Ext/Vardefs into vardefs.ext.php
591      */
592         function install_vardefs(){
593         if(isset($this->installdefs['vardefs'])){
594                         $this->log(translate('LBL_MI_IN_VAR') );
595                         foreach($this->installdefs['vardefs'] as $vardefs){
596                                 $vardefs['from'] = str_replace('<basepath>', $this->base_dir, $vardefs['from']);
597                                 $this->install_vardef($vardefs['from'], $vardefs['to_module'], $this->id_name);
598                         }
599                         $this->rebuild_vardefs();
600                 }
601         }
602         function uninstall_vardefs(){
603         if(isset($this->installdefs['vardefs'])){
604                                         $this->log(translate('LBL_MI_UN_VAR') );
605                                         foreach($this->installdefs['vardefs'] as $vardefs){
606                                                 $vardefs['from'] = str_replace('<basepath>', $this->base_dir, $vardefs['from']);
607                                                 $GLOBALS['log']->debug("Uninstalling Vardefs ..." . $vardefs['from'] .  " for " .$vardefs['to_module']);
608                                                 $path = 'custom/Extension/modules/' . $vardefs['to_module']. '/Ext/Vardefs';
609                                                 if($vardefs['to_module'] == 'application'){
610                                                         $path ='custom/Extension/' . $vardefs['to_module']. '/Ext/Vardefs';
611                                                 }
612                                                 if(file_exists($path . '/'. $this->id_name . '.php'))
613                                                 {
614                                                         rmdir_recursive( $path . '/'. $this->id_name . '.php');
615                                                 }
616                                                 else if(file_exists($path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php'))
617                                                 {
618                                                         rmdir_recursive($path . '/'. DISABLED_PATH . '/'. $this->id_name . '.php');
619                                                 }
620                                                 else if (file_exists($path . '/'. basename($vardefs['from'] )))
621                                                 {
622                                                         rmdir_recursive( $path . '/'. basename($vardefs['from'] ));
623                                                 }
624                                                 else if(file_exists($path . '/'. DISABLED_PATH . '/'.  basename($vardefs['from'])))
625                                                 {
626                                                         rmdir_recursive($path . '/'. DISABLED_PATH . '/'.  basename($vardefs['from']));
627                                                 }
628                                         }
629                                         $this->rebuild_vardefs();
630                                 }
631         }
632         function install_vardef($from, $to_module){
633                         $GLOBALS['log']->debug("Installing Vardefs ..." . $from .  " for " .$to_module);
634                         $path = 'custom/Extension/modules/' . $to_module. '/Ext/Vardefs';
635                         if($to_module == 'application'){
636                                 $path ='custom/Extension/' . $to_module. '/Ext/Vardefs';
637                         }
638                         if(!file_exists($path)){
639                                 mkdir_recursive($path, true);
640                         }
641                         copy_recursive($from , $path.'/'. basename($from));
642         }
643
644         /*
645      * ModuleInstaller->install_layoutdefs installs the $layout_defs variable (subpanel definitions) from Ext/Layoutdefs to the to_module location of
646      * custom/Extension/modules/' . $to_module. '/Ext/Layoutdefs/<$module>.php. before calling rebuild_layoutdefs which merge_files Ext/Layoutdefs/, 'layoutdefs.ext.php'. Note that this is not used for the viewdefs in the metadata directory - they are installed through the install_copy() operation that just takes the contents of the module directory and places it in the /modules area.
647      */
648         function install_layoutdefs(){
649         if(isset($this->installdefs['layoutdefs'])){
650                         $this->log(translate('LBL_MI_IN_SUBPANEL') );
651                         foreach($this->installdefs['layoutdefs'] as $layoutdefs){
652                                 $layoutdefs['from'] = str_replace('<basepath>', $this->base_dir, $layoutdefs['from']);
653                                 $this->install_layoutdef($layoutdefs['from'], $layoutdefs['to_module'], $this->id_name);
654                         }
655                         $this->rebuild_layoutdefs();
656                 }
657         }
658         function uninstall_layoutdefs(){
659         if(isset($this->installdefs['layoutdefs'])){
660                                         $this->log(translate('LBL_MI_UN_SUBPANEL') );
661                                         foreach($this->installdefs['layoutdefs'] as $layoutdefs){
662                                                 $layoutdefs['from'] = str_replace('<basepath>', $this->base_dir, $layoutdefs['from']);
663                                                 $GLOBALS['log']->debug("Uninstalling Layoutdefs ..." . $layoutdefs['from'] .  " for " .$layoutdefs['to_module']);
664                                                 $path = 'custom/Extension/modules/' . $layoutdefs['to_module']. '/Ext/Layoutdefs';
665                                                 if($layoutdefs['to_module'] == 'application'){
666                                                         $path ='custom/Extension/' . $layoutdefs['to_module']. '/Ext/Layoutdefs';
667                                                 }
668                                                 if (file_exists($path . '/'. $this->id_name . '.php'))
669                                                 {
670                                                         rmdir_recursive( $path . '/'. $this->id_name . '.php');
671                                                 }
672                                                 else if (file_exists($path . '/'. DISABLED_PATH . '/' . $this->id_name . '.php'))
673                                                 {
674                                                         rmdir_recursive($path . '/'. DISABLED_PATH . '/' . $this->id_name . '.php');
675                                                 }
676                                                 else if (file_exists($path . '/'. basename($layoutdefs['from'] )))
677                                                 {
678                                                         rmdir_recursive( $path . '/'. basename($layoutdefs['from'] ));
679                                                 }
680                                                 else if(file_exists($path . '/'. DISABLED_PATH . '/'.  basename($layoutdefs['from'])))
681                                                 {
682                                                         rmdir_recursive($path . '/'. DISABLED_PATH . '/'.  basename($layoutdefs['from']));
683                                                 }
684                                         }
685                                         $this->rebuild_layoutdefs();
686                                 }
687         }
688         function install_layoutdef($from, $to_module){
689                         $GLOBALS['log']->debug("Installing Layout Defs ..." . $from .  " for " .$to_module);
690                         $path = 'custom/Extension/modules/' . $to_module. '/Ext/Layoutdefs';
691                         if($to_module == 'application'){
692                                 $path ='custom/Extension/' . $to_module. '/Ext/Layoutdefs';
693                         }
694                         if(!file_exists($path)){
695                                 mkdir_recursive($path, true);
696                         }
697                         copy_recursive($from , $path.'/'. basename($from));
698         }
699
700         function install_languages()
701         {
702         $languages = array();
703         if(isset($this->installdefs['language']))
704         {
705             $this->log(translate('LBL_MI_IN_LANG') );
706             foreach($this->installdefs['language'] as $packs)
707             {
708                 $modules[]=$packs['to_module'];
709                 $languages[$packs['language']] = $packs['language'];
710                                 $packs['from'] = str_replace('<basepath>', $this->base_dir, $packs['from']);
711                                 $GLOBALS['log']->debug("Installing Language Pack ..." . $packs['from']  .  " for " .$packs['to_module']);
712                             $path = 'custom/Extension/modules/' . $packs['to_module']. '/Ext/Language';
713                                 if($packs['to_module'] == 'application'){
714                                     $path ='custom/Extension/' . $packs['to_module']. '/Ext/Language';
715                                 }
716
717                                 if(!file_exists($path)){
718                                     mkdir_recursive($path, true);
719                 }
720                                 copy_recursive($packs['from'] , $path.'/'.$packs['language'].'.'. $this->id_name . '.php');
721                         }
722                         $this->rebuild_languages($languages, $modules);
723
724                 }
725         }
726
727         function uninstall_languages(){
728         $languages = array();
729                                 if(isset($this->installdefs['language'])){
730                                         $this->log(translate('LBL_MI_UN_LANG') );
731                                         foreach($this->installdefs['language'] as $packs){
732                                                 $modules[]=$packs['to_module'];
733                                                 $languages[$packs['language']] = $packs['language'];
734                                                 $packs['from'] = str_replace('<basepath>', $this->base_dir, $packs['from']);
735                                                 $GLOBALS['log']->debug("Uninstalling Language Pack ..." . $packs['from']  .  " for " .$packs['to_module']);
736                                                 $path = 'custom/Extension/modules/' . $packs['to_module']. '/Ext/Language';
737                                                 if($packs['to_module'] == 'application'){
738                                                         $path ='custom/Extension/' . $packs['to_module']. '/Ext/Language';
739                                                 }
740                                                 if (sugar_is_file($path.'/'.$packs['language'].'.'. $this->id_name . '.php', 'w')) {
741                                                         rmdir_recursive( $path.'/'.$packs['language'].'.'. $this->id_name . '.php');
742                                                 } else if (sugar_is_file($path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php', 'w')) {
743                                                         rmdir_recursive($path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php', 'w');
744                                                 }
745                                         }
746                                         $this->rebuild_languages($languages, $modules);
747
748                                 }
749         }
750
751     // Functions for adding and removing logic hooks from uploaded files
752     // Since one class/file can be used by multiple logic hooks, I'm not going to touch the file labeled in the logic_hook entry
753     /* The module hook definition should look like this:
754      $installdefs = array(
755      ... blah blah ...
756          'logic_hooks' => array(
757              array('module'      => 'Accounts',
758                    'hook'        => 'after_save',
759                    'order'       => 99,
760                    'description' => 'Account sample logic hook',
761                    'file'        => 'modules/Sample/sample_account_logic_hook_file.php',
762                    'class'       => 'SampleLogicClass',
763                    'function'    => 'accountAfterSave',
764              ),
765          ),
766      ... blah blah ...
767      );
768      */
769     function install_logichooks() {
770         // Since the logic hook files get copied over with the rest of the module directory, we just need to enable them
771         $this->enable_logichooks();
772     }
773
774     function uninstall_logichooks() {
775         // Since the logic hook files get removed with the rest of the module directory, we just need to disable them
776         $this->disable_logichooks();
777     }
778
779     function enable_logichooks() {
780         if(empty($this->installdefs['logic_hooks']) || !is_array($this->installdefs['logic_hooks'])) {
781            return;
782         }
783
784
785
786         foreach($this->installdefs['logic_hooks'] as $hook ) {
787             check_logic_hook_file($hook['module'], $hook['hook'], array($hook['order'], $hook['description'],  $hook['file'], $hook['class'], $hook['function']));
788         }
789     }
790
791     function disable_logichooks() {
792         if(empty($this->installdefs['logic_hooks']) || !is_array($this->installdefs['logic_hooks'])) {
793             return;
794         }
795
796
797         foreach($this->installdefs['logic_hooks'] as $hook ) {
798             remove_logic_hook($hook['module'], $hook['hook'], array($hook['order'], $hook['description'],  $hook['file'], $hook['class'], $hook['function']));
799         }
800     }
801
802 /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
803         function copy_path($from, $to, $backup_path='', $uninstall=false){
804         //function copy_path($from, $to){
805 /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
806                 $to = str_replace('<basepath>', $this->base_dir, $to);
807
808                 if(!$uninstall) {
809                 $from = str_replace('<basepath>', $this->base_dir, $from);
810                 $GLOBALS['log']->debug('Copy ' . $from);
811                 }
812                 else {
813                         $from = str_replace('<basepath>', $backup_path, $from);
814                         //$GLOBALS['log']->debug('Restore ' . $from);
815                 }
816                 $from = clean_path($from);
817                 $to = clean_path($to);
818
819                 $dir = dirname($to);
820                 //there are cases where if we need to create a directory in the root directory
821                 if($dir == '.' && is_dir($from)){
822                         $dir = $to;
823                 }
824                 if(!sugar_is_dir($dir, 'instance'))
825                         mkdir_recursive($dir, true);
826 /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
827                 if(empty($backup_path)) {
828 /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
829                 if(!copy_recursive($from, $to)){
830                         die('Failed to copy ' . $from. ' ' . $to);
831                 }
832 /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
833                 }
834                 elseif(!$this->copy_recursive_with_backup($from, $to, $backup_path, $uninstall)){
835                         die('Failed to copy ' . $from. ' to ' . $to);
836                 }
837 /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:22:18 PM */
838         }
839
840         function install_custom_fields($fields){
841                 global $beanList, $beanFiles;
842                 include('include/modules.php');
843                 require_once('modules/DynamicFields/FieldCases.php');
844                 foreach($fields as $field){
845                         $installed = false;
846                         if(isset($beanList[ $field['module']])){
847                                 $class = $beanList[ $field['module']];
848                 if(!isset($field['ext4']))$field['ext4'] = '';
849                 if(!isset($field['mass_update']))$field['mass_update'] = 0;
850                 if(!isset($field['duplicate_merge']))$field['duplicate_merge'] = 0;
851                 if(!isset($field['help']))$field['help'] = '';
852
853                                 if(file_exists($beanFiles[$class])){
854                                         require_once($beanFiles[$class]);
855                                         $mod = new $class();
856                                         $installed = true;
857                                         $fieldObject = get_widget($field['type']);
858                                         $fieldObject->populateFromRow($field);
859                                         $mod->custom_fields->use_existing_labels =  true;
860                                         $mod->custom_fields->addFieldObject($fieldObject);
861                                 }
862                         }
863                         if(!$installed){
864                                 $GLOBALS['log']->debug('Could not install custom field ' . $field['name'] . ' for module ' .  $field['module'] . ': Module does not exist');
865                         }
866                 }
867         }
868
869         function uninstall_custom_fields($fields){
870                 global $beanList, $beanFiles;
871                 require_once('modules/DynamicFields/DynamicField.php');
872                 $dyField = new DynamicField();
873
874                 foreach($fields as $field){
875                         $class = $beanList[ $field['module']];
876                         if(file_exists($beanFiles[$class])){
877                                         require_once($beanFiles[$class]);
878                                         $mod = new $class();
879                                         $dyField->bean = $mod;
880                                         $dyField->module = $field['module'];
881                                         $dyField->deleteField($field['name']);
882                         }
883                 }
884         }
885
886         /*
887      * ModuleInstaller->install_relationships calls install_relationship for every file included in the module package that defines a relationship, and then
888      * writes a custom/Extension/application/Ext/TableDictionary/$module.php file containing an include_once for every relationship metadata file passed to install_relationship.
889      * Next it calls install_vardef and install_layoutdef. Finally, it rebuilds the vardefs and layoutdefs (by calling merge_files as usual), and then calls merge_files to merge
890      * everything in 'Ext/TableDictionary/' into 'tabledictionary.ext.php'
891      */
892     function install_relationships ()
893     {
894         if (isset ( $this->installdefs [ 'relationships' ] ))
895         {
896             $this->log ( translate ( 'LBL_MI_IN_RELATIONSHIPS' ) ) ;
897             $str = "<?php \n //WARNING: The contents of this file are auto-generated\n" ;
898             $save_table_dictionary = false ;
899
900             if (! file_exists ( "custom/Extension/application/Ext/TableDictionary" ))
901             {
902                 mkdir_recursive ( "custom/Extension/application/Ext/TableDictionary", true ) ;
903             }
904
905             foreach ( $this->installdefs [ 'relationships' ] as $key => $relationship )
906             {
907                 $filename = basename ( $relationship [ 'meta_data' ] ) ;
908                 $this->copy_path ( $relationship [ 'meta_data' ], 'custom/metadata/' . $filename ) ;
909                 $this->install_relationship ( 'custom/metadata/' . $filename ) ;
910                 $save_table_dictionary = true ;
911
912                 if (! empty ( $relationship [ 'module_vardefs' ] ))
913                 {
914                     $relationship [ 'module_vardefs' ] = str_replace ( '<basepath>', $this->base_dir, $relationship [ 'module_vardefs' ] ) ;
915                     $this->install_vardef ( $relationship [ 'module_vardefs' ], $relationship [ 'module' ] ) ;
916                 }
917
918                 if (! empty ( $relationship [ 'module_layoutdefs' ] ))
919                 {
920                     $relationship [ 'module_layoutdefs' ] = str_replace ( '<basepath>', $this->base_dir, $relationship [ 'module_layoutdefs' ] ) ;
921                     $this->install_layoutdef ( $relationship [ 'module_layoutdefs' ], $relationship [ 'module' ] ) ;
922                 }
923
924                 $relName = strpos($filename, "MetaData") !== false ? substr($filename, 0, strlen($filename) - 12) : $filename;
925                 $out = sugar_fopen ( "custom/Extension/application/Ext/TableDictionary/$relName.php", 'w' ) ;
926                 fwrite ( $out, $str . "include('custom/metadata/$filename');\n\n?>" ) ;
927                 fclose ( $out ) ;
928             }
929
930
931
932             $this->rebuild_vardefs () ;
933             $this->rebuild_layoutdefs () ;
934             if ($save_table_dictionary)
935             {
936                 $this->rebuild_tabledictionary () ;
937             }
938
939         }
940     }
941
942         /*
943      * Install_relationship obtains a set of relationship definitions from the filename passed in as a parameter.
944      * For each definition it calls db->createTableParams to build the relationships table if it does not exist,
945      * and SugarBean::createRelationshipMeta to add the relationship into the 'relationships' table.
946      */
947         function install_relationship($file)
948         {
949                 $_REQUEST['moduleInstaller'] = true;
950                 if(!file_exists($file))
951                 {
952                         $GLOBALS['log']->debug( 'File does not exists : '.$file);
953                         return;
954                 }
955                 include($file);
956                 $rel_dictionary = $dictionary;
957                 foreach ($rel_dictionary as $rel_name => $rel_data)
958             {
959                 $table = ''; // table is actually optional
960                 // check if we have a table definition - not all relationships require a join table
961             if ( isset( $rel_data[ 'table' ] ) )
962             {
963                 $table = $rel_data[ 'table' ];
964
965                 if(!$this->db->tableExists($table))
966                 {
967                     $this->db->createTableParams($table, $rel_data[ 'fields' ], $rel_data[ 'indices' ]);
968                 }
969             }
970
971             if(!$this->silent)
972                 $GLOBALS['log']->debug("Processing relationship meta for ". $rel_name."...");
973             SugarBean::createRelationshipMeta($rel_name, $this->db,$table,$rel_dictionary,'');
974             Relationship::delete_cache();
975             if(!$this->silent)
976                 $GLOBALS['log']->debug( 'done<br>');
977         }
978         }
979
980         function install_layoutfields() {
981                  if (!empty ( $this->installdefs [ 'layoutfields' ] ))
982                  {
983                         foreach ( $this->installdefs [ 'layoutfields' ] as $fieldSet )
984             {
985                                 if (!empty($fieldSet['additional_fields']))
986                                 {
987                                         $this->addFieldsToLayout($fieldSet['additional_fields']);
988                                 }
989             }
990                  }
991         }
992
993         function uninstall_layoutfields() {
994                  if (!empty ( $this->installdefs [ 'layoutfields' ] ))
995                  {
996                         foreach ( $this->installdefs [ 'layoutfields' ] as $fieldSet )
997             {
998                                 if (!empty($fieldSet['additional_fields']))
999                                 {
1000                                         $this->removeFieldsFromLayout($fieldSet['additional_fields']);
1001                                 }
1002             }
1003                  }
1004         }
1005
1006         function uninstall_relationship($file, $rel_dictionary = null){
1007         if ($rel_dictionary == null)
1008                 {
1009                         if(!file_exists($file)){
1010                                 $GLOBALS['log']->debug( 'File does not exists : '.$file);
1011                                 return;
1012                         }
1013                         include($file);
1014                         $rel_dictionary = $dictionary;
1015                 }
1016
1017                 foreach ($rel_dictionary as $rel_name => $rel_data)
1018                 {
1019                         if (!empty($rel_data['table'])){
1020                                 $table = $rel_data['table'];
1021                         }
1022                         else{
1023                                 $table = ' One-to-Many ';
1024                         }
1025
1026                         if ($this->db->tableExists($table) && isset($GLOBALS['mi_remove_tables']) && $GLOBALS['mi_remove_tables'])
1027                         {
1028                                 SugarBean::removeRelationshipMeta($rel_name, $this->db,$table,$rel_dictionary,'');
1029                                 $this->db->dropTableName($table);
1030                                 if(!$this->silent) $this->log( translate('LBL_MI_UN_RELATIONSHIPS_DROP') . $table);
1031                         }
1032
1033                         //Delete Layout defs
1034                         // check to see if we have any vardef or layoutdef entries to remove - must have a relationship['module'] parameter if we do
1035                         if (!isset($rel_data[ 'module' ]))
1036                                 $mods = array(
1037                                         $rel_data['relationships'][$rel_name]['lhs_module'],
1038                                         $rel_data['relationships'][$rel_name]['rhs_module'],
1039                                 );
1040                         else
1041                                 $mods = array($rel_data[ 'module' ]);
1042
1043                         $filename = "$rel_name.php";
1044
1045                         foreach($mods as $mod) {
1046                                 if ($mod != 'application' )  {
1047                                         $basepath = "custom/Extension/modules/$mod/Ext/";
1048                                 } else {
1049                                         $basepath = "custom/Extension/application/Ext/";
1050                                 }
1051
1052                                 foreach (array($filename , "custom" . $filename, $rel_name ."_". $mod. ".php") as $fn) {
1053                                         //remove any vardefs
1054                                         $path = $basepath . "Vardefs/$fn" ;
1055                                         if (file_exists( $path ))
1056                                                 rmdir_recursive( $path );
1057
1058                                         //remove any layoutdefs
1059                                         $path = $basepath . "Layoutdefs/$fn" ;
1060                                         if( file_exists( $path ))
1061                                         {
1062                                                 rmdir_recursive( $path );
1063                                         }
1064                                 }
1065                         }
1066
1067                         foreach (array($filename , "custom" . $filename, $rel_name ."_". $mod. ".php") as $fn) {
1068                                 // remove the table dictionary extension
1069                                 if ( file_exists("custom/Extension/application/Ext/TableDictionary/$fn"))
1070                                     unlink("custom/Extension/application/Ext/TableDictionary/$fn");
1071
1072                                 if (file_exists("custom/metadata/{$rel_name}MetaData.php"))
1073                                         unlink( "custom/metadata/{$rel_name}MetaData.php" );
1074                         }
1075                 }
1076         }
1077
1078         function uninstall_relationships($include_studio_relationships = false){
1079                 $relationships = array();
1080
1081                 //Find and remove studio created relationships.
1082                 global $beanList, $beanFiles, $dictionary;
1083                 //Load up the custom relationship definitions.
1084                 if(file_exists('custom/application/Ext/TableDictionary/tabledictionary.ext.php')){
1085                         include('custom/application/Ext/TableDictionary/tabledictionary.ext.php');
1086                 }
1087                 //Find all the relatioships/relate fields involving this module.
1088                 $rels_to_remove = array();
1089                 foreach($beanList as $mod => $bean) {
1090                         VardefManager::loadVardef($mod, $bean);
1091                         //We can skip modules that are in this package as they will be removed anyhow
1092                         if (!in_array($mod, $this->modulesInPackage) && !empty($dictionary[$bean]) && !empty($dictionary[$bean]['fields']))
1093                         {
1094                                 $field_defs = $dictionary[$bean]['fields'];
1095                                 foreach($field_defs as $field => $def)
1096                                 {
1097                                         //Weed out most fields first
1098                                         if (isset ($def['type']))
1099                                         {
1100                                                 //Custom relationships created in the relationship editor
1101                                                 if ($def['type'] == "link" && !empty($def['relationship']) && !empty($dictionary[$def['relationship']]))
1102                                                 {
1103                                                         $rel_name = $def['relationship'];
1104
1105                                                         $rel_def = $dictionary[$rel_name]['relationships'][$rel_name];
1106
1107                                                         //Check against mods to be removed.
1108                                                         foreach($this->modulesInPackage as $removed_mod) {
1109                                                                 if ($rel_def['lhs_module'] == $removed_mod || $rel_def['rhs_module'] == $removed_mod )
1110                                                                 {
1111                                                                         $dictionary[$rel_name]['from_studio'] = true;
1112                                                                         $relationships[$rel_name] = $dictionary[$rel_name];
1113                                                                 }
1114                                                         }
1115                                                 }
1116                                                 //Custom "relate" fields created in studio also need to be removed
1117                                                 if ($def['type'] == 'relate' && isset($def['module'])) {
1118                                                         foreach($this->modulesInPackage as $removed_mod) {
1119                                                                 if ($def['module'] == $removed_mod)
1120                                                                 {
1121                                                                         require_once 'modules/ModuleBuilder/Module/StudioModule.php' ;
1122                                                                         $studioMod = new StudioModule ( $mod );
1123                                                                         $studioMod->removeFieldFromLayouts( $field );
1124                                                                         if (isset($def['custom_module'])) {
1125                                                                                 require_once ('modules/DynamicFields/DynamicField.php') ;
1126                                                                                 require_once ($beanFiles [ $bean ]) ;
1127                                                                                 $seed = new $bean ( ) ;
1128                                                                                 $df = new DynamicField ( $mod ) ;
1129                                                                                 $df->setup ( $seed ) ;
1130                                                                                 //Need to load the entire field_meta_data for some field types
1131                                                                                 $field_obj = $df->getFieldWidget($mod, $field);
1132                                                                                 $field_obj->delete ( $df ) ;
1133                                                                         }
1134                                                                 }
1135                                                         }
1136                                                 }
1137                                         }
1138                                 }
1139                         }
1140                 }
1141
1142
1143
1144                 $this->uninstall_relationship(null, $relationships);
1145
1146                 if(isset($this->installdefs['relationships'])) {
1147                         $relationships = $this->installdefs['relationships'];
1148                         $this->log(translate('LBL_MI_UN_RELATIONSHIPS') );
1149                         foreach($relationships as $relationship)
1150                         {
1151                                 // remove the metadata entry
1152                                 $filename = basename ( $relationship['meta_data'] );
1153                                 $pathname = (file_exists("custom/metadata/$filename")) ? "custom/metadata/$filename" : "metadata/$filename" ;
1154                                 if(isset($GLOBALS['mi_remove_tables']) && $GLOBALS['mi_remove_tables'])
1155                                 $this->uninstall_relationship( $pathname );
1156                                 if (file_exists($pathname))
1157                                         unlink( $pathname );
1158                         }
1159                 }
1160
1161                 if (file_exists("custom/Extension/application/Ext/TableDictionary/{$this->id_name}.php"))
1162                         unlink("custom/Extension/application/Ext/TableDictionary/{$this->id_name}.php");
1163                 Relationship::delete_cache();
1164                 $this->rebuild_tabledictionary();
1165         }
1166
1167
1168
1169
1170         function uninstall($base_dir){
1171                 if(defined('TEMPLATE_URL'))SugarTemplateUtilities::disableCache();
1172                 global $app_strings;
1173                 $total_steps = 5; //min steps with no tasks
1174                 $current_step = 0;
1175                 $this->base_dir = $base_dir;
1176                 $tasks = array(
1177                         'pre_uninstall',
1178                         'uninstall_relationships',
1179                         'uninstall_copy',
1180                         'uninstall_dcactions',
1181                         'uninstall_menus',
1182                         'uninstall_dashlets',
1183                         'uninstall_userpage',
1184                         'uninstall_administration',
1185                         'uninstall_connectors',
1186                         'uninstall_vardefs',
1187                         'uninstall_layoutdefs',
1188                         'uninstall_layoutfields',
1189                         'uninstall_languages',
1190                         'uninstall_logichooks',
1191                         'post_uninstall',
1192                 );
1193                 $total_steps += count($tasks); //now the real number of steps
1194                 if(file_exists($this->base_dir . '/manifest.php')){
1195                                 if(!$this->silent){
1196                                         $current_step++;
1197                                         display_progress_bar('install', $current_step, $total_steps);
1198                                         echo '<div id ="displayLoglink" ><a href="#" onclick="toggleDisplay(\'displayLog\')">'.$app_strings['LBL_DISPLAY_LOG'].'</a> </div><div id="displayLog" style="display:none">';
1199                                 }
1200
1201                                 global $moduleList;
1202                                 include($this->base_dir . '/manifest.php');
1203                                 $this->installdefs = $installdefs;
1204                                 $this->id_name = $this->installdefs['id'];
1205                                 $installed_modules = array();
1206                                 if(isset($this->installdefs['beans'])){
1207
1208                                         foreach($this->installdefs['beans'] as $bean){
1209
1210                                                 $installed_modules[] = $bean['module'];
1211                                                 $this->uninstall_user_prefs($bean['module']);
1212                                         }
1213                                         $this->modulesInPackage = $installed_modules;
1214                                         $this->uninstall_beans($installed_modules);
1215                                         $this->uninstall_customizations($installed_modules);
1216                                         if(!$this->silent){
1217                                                 $current_step++;
1218                                                 update_progress_bar('install', $total_steps, $total_steps);
1219                                         }
1220                                         if (sugar_is_file("custom/Extension/application/Ext/Include/$this->id_name.php", 'w'))
1221                                                 rmdir_recursive("custom/Extension/application/Ext/Include/$this->id_name.php");
1222                                         else if(sugar_is_file("custom/Extension/application/Ext/Include/" . DISABLED_PATH . "/$this->id_name.php", 'w'))
1223                                                 rmdir_recursive("custom/Extension/application/Ext/Include/" . DISABLED_PATH . "/$this->id_name.php");
1224
1225                                         $this->rebuild_modules();
1226                                 }
1227                                 if(!$this->silent){
1228                                         $current_step++;
1229                                         update_progress_bar('install', $current_step, $total_steps);
1230                                 }
1231
1232
1233                                 foreach($tasks as $task){
1234                                         $this->$task();
1235                                         if(!$this->silent){
1236                                                 $current_step++;
1237                                                 update_progress_bar('install', $current_step, $total_steps);
1238                                         }
1239                                 }
1240                                 if(isset($installdefs['custom_fields']) && (isset($GLOBALS['mi_remove_tables']) && $GLOBALS['mi_remove_tables'])){
1241                                         $this->log(translate('LBL_MI_UN_CUSTOMFIELD'));
1242                                         $this->uninstall_custom_fields($installdefs['custom_fields']);
1243                                 }
1244                                 if(!$this->silent){
1245                                         $current_step++;
1246                                         update_progress_bar('install', $current_step, $total_steps);
1247                                         echo '</div>';
1248                                 }
1249                                 //since we are passing $silent = true to rebuildAll() in that method it will set $this->silent = true, so
1250                                 //we need to save the setting to set it back after rebuildAll() completes.
1251                                 $silentBak = $this->silent;
1252                                 $this->rebuild_all(true);
1253                                 $this->silent = $silentBak;
1254
1255                                 //#27877, If the request from MB redeploy a custom module , we will not remove the ACL actions for this package.
1256                                 if( !isset($_REQUEST['action']) || $_REQUEST['action']!='DeployPackage' ){
1257                                         $this->remove_acl_actions();
1258                                 }
1259                                 //end
1260
1261                                 if(!$this->silent){
1262                                         $current_step++;
1263                                         update_progress_bar('install', $current_step, $total_steps);
1264                                         echo '</div>';
1265                                 }
1266
1267                                 UpdateSystemTabs('Restore',$installed_modules);
1268
1269                     //clear the unified_search_module.php file 
1270                     require_once('modules/Home/UnifiedSearchAdvanced.php');
1271                     UnifiedSearchAdvanced::unlinkUnifiedSearchModulesFile();                                    
1272                                 
1273                                 $this->log('<br><b>' . translate('LBL_MI_COMPLETE') . '</b>');
1274                                 if(!$this->silent){
1275                                         update_progress_bar('install', $total_steps, $total_steps);
1276                                 }
1277                 }else{
1278                         die("No manifest.php Defined In $this->base_dir/manifest.php");
1279                 }
1280         }
1281
1282         function rebuild_languages($languages, $modules=""){
1283             foreach($languages as $language=>$value){
1284                                 $this->log(translate('LBL_MI_REBUILDING') . " Language...$language");
1285                                 $this->merge_files('Ext/Language/', $language.'.lang.ext.php', $language);
1286                     if($modules!=""){
1287                         foreach($modules as $module){
1288                                 LanguageManager::clearLanguageCache($module, $language);
1289                         }
1290                     }
1291                         }
1292                         sugar_cache_reset();
1293
1294         }
1295
1296         function rebuild_vardefs(){
1297             $this->log(translate('LBL_MI_REBUILDING') . " Vardefs...");
1298                         $this->merge_files('Ext/Vardefs/', 'vardefs.ext.php');
1299                         sugar_cache_reset();
1300         }
1301
1302         function rebuild_layoutdefs(){
1303             $this->log(translate('LBL_MI_REBUILDING') . " Layoutdefs...");
1304                         $this->merge_files('Ext/Layoutdefs/', 'layoutdefs.ext.php');
1305
1306         }
1307
1308         function rebuild_menus(){
1309             $this->log(translate('LBL_MI_REBUILDING') . " Menus...");
1310                         $this->merge_files('Ext/Menus/', 'menu.ext.php');
1311         }
1312
1313         function rebuild_dashletcontainers(){
1314             $this->log(translate('LBL_MI_REBUILDING') . " DC Actions...");
1315                         $this->merge_files('Ext/DashletContainer/Containers/', 'dcactions.ext.php');
1316         }
1317
1318         function rebuild_modules(){
1319             $this->log(translate('LBL_MI_REBUILDING') . " Modules...");
1320                         $this->merge_files('Ext/Include/', 'modules.ext.php', '', true);
1321         }
1322
1323         function rebuild_administration(){
1324             $this->log(translate('LBL_MI_REBUILDING') . " administration " . translate('LBL_MI_SECTION'));
1325                         $this->merge_files('Ext/Administration/', 'administration.ext.php');
1326         }
1327         function rebuild_userpage(){
1328             $this->log(translate('LBL_MI_REBUILDING') . " User Page " . translate('LBL_MI_SECTION'));
1329                         $this->merge_files('Ext/UserPage/', 'userpage.ext.php');
1330         }
1331         function rebuild_tabledictionary(){
1332             $this->log(translate('LBL_MI_REBUILDING') . " administration " . translate('LBL_MI_SECTION'));
1333                         $this->merge_files('Ext/TableDictionary/', 'tabledictionary.ext.php');
1334         }
1335
1336         function rebuild_relationships() {
1337         if(!$this->silent) echo translate('LBL_MI_REBUILDING') . ' Relationships';
1338                 $_REQUEST['silent'] = true;
1339                 global $beanFiles;
1340                 include('include/modules.php');
1341                 include("modules/Administration/RebuildRelationship.php");
1342         }
1343
1344         function remove_acl_actions() {
1345                 global $beanFiles, $beanList, $current_user;
1346                 include('include/modules.php');
1347                 include("modules/ACL/remove_actions.php");
1348         }
1349
1350         /**
1351          * Wrapper call to modules/Administration/RepairIndex.php
1352          */
1353         function repair_indices() {
1354                 global $current_user,$beanFiles,$dictionary;
1355                 $this->log(translate('LBL_MI_REPAIR_INDICES'));
1356                 $_REQUEST['silent'] = true; // local var flagging echo'd output in repair script
1357                 $_REQUEST['mode'] = 'execute'; // flag to just go ahead and run the script
1358                 include("modules/Administration/RepairIndex.php");
1359         }
1360
1361         /**
1362          * Rebuilds the extension files found in custom/Extension
1363          * @param boolean $silent
1364          */
1365         function rebuild_all($silent=false){
1366                 if(defined('TEMPLATE_URL'))SugarTemplateUtilities::disableCache();
1367                 $this->silent=$silent;
1368                 global $sugar_config;
1369
1370                 //Check for new module extensions
1371                 $this->rebuild_modules();
1372
1373                 $this->rebuild_languages($sugar_config['languages']);
1374                 $this->rebuild_vardefs();
1375                 $this->rebuild_layoutdefs();
1376                 $this->rebuild_menus();
1377                 $this->rebuild_dashletcontainers();
1378                 $this->rebuild_userpage();
1379                 $this->rebuild_administration();
1380                 $this->rebuild_relationships();
1381                 $this->rebuild_tabledictionary();
1382                 //$this->repair_indices();
1383                 $this->reset_opcodes();
1384                 sugar_cache_reset();
1385         }
1386
1387         /*
1388      * ModuleInstaller->merge_files runs over the list of all modules already installed in /modules. For each $module it reads the contents of every file in
1389      * custom/Extension/modules/$module/<path> (_override files last) and concatenates them to custom/modules/$module/<path>/<file>.
1390      * Then it does the same thing in custom/Extension/application/<path>, concatenating those files and copying the result to custom/application/<path>/<file>
1391      */
1392         function merge_files($path, $name, $filter = '', $application = false){
1393                 if(!$application){
1394                 $GLOBALS['log']->debug( get_class($this)."->merge_files() : merging module files in custom/Extension/modules/<module>/$path to custom/modules/<module>/$path$name");
1395                 foreach($this->modules as $module){
1396                                 //$GLOBALS['log']->debug("Merging Files for: ".$module);
1397                                 //$GLOBALS['log']->debug("Merging Files for path: ".$path);
1398                                 $extension = "<?php \n //WARNING: The contents of this file are auto-generated\n";
1399                                 $extpath = "modules/$module/$path";
1400                                 $module_install  = 'custom/Extension/'.$extpath;
1401                                 $shouldSave = false;
1402                                 if(is_dir($module_install)){
1403                                         $dir = dir($module_install);
1404                                         $shouldSave = true;
1405                                         $override = array();
1406                                         while($entry = $dir->read()){
1407                                                 if((empty($filter) || substr_count($entry, $filter) > 0) && is_file($module_install.'/'.$entry)
1408                                                   && $entry != '.' && $entry != '..' && strtolower(substr($entry, -4)) == ".php")
1409                                                 {
1410                                                      if (substr($entry, 0, 9) == '_override') {
1411                                                         $override[] = $entry;
1412                                                     } else {
1413                                                             $file = file_get_contents($module_install . '/' . $entry);
1414                                                             $GLOBALS['log']->debug(get_class($this)."->merge_files(): found {$module_install}{$entry}") ;
1415                                                             $extension .= "\n". str_replace(array('<?php', '?>', '<?PHP', '<?'), array('','', '' ,'') , $file);
1416                                                     }
1417                                                 }
1418                                         }
1419                                         foreach ($override as $entry) {
1420                         $file = file_get_contents($module_install . '/' . $entry);
1421                         $extension .= "\n". str_replace(array('<?php', '?>', '<?PHP', '<?'), array('','', '' ,'') , $file);
1422                                         }
1423                                 }
1424                                 $extension .= "\n?>";
1425
1426                                 if($shouldSave){
1427                                         if(!file_exists("custom/$extpath")){
1428                                         mkdir_recursive("custom/$extpath", true);
1429                                 }
1430                                         $out = sugar_fopen("custom/$extpath/$name", 'w');
1431                                         fwrite($out,$extension);
1432                                         fclose($out);
1433                                 }else{
1434                                         if(file_exists("custom/$extpath/$name")){
1435                                                 unlink("custom/$extpath/$name");
1436                                         }
1437                                 }
1438                         }
1439
1440                 }
1441
1442                 $GLOBALS['log']->debug("Merging application files for $name in $path");
1443                 //Now the application stuff
1444                 $extension = "<?php \n //WARNING: The contents of this file are auto-generated\n";
1445                 $extpath = "application/$path";
1446                 $module_install  = 'custom/Extension/'.$extpath;
1447                 $shouldSave = false;
1448                                         if(is_dir($module_install)){
1449                                                 $dir = dir($module_install);
1450                                                 while($entry = $dir->read()){
1451                                                                 $shouldSave = true;
1452                                                                 if((empty($filter) || substr_count($entry, $filter) > 0) && is_file($module_install.'/'.$entry)
1453                                                                   && $entry != '.' && $entry != '..' && strtolower(substr($entry, -4)) == ".php")
1454                                                                 {
1455                                                                         $file = file_get_contents($module_install . '/' . $entry);
1456                                                                         $extension .= "\n". str_replace(array('<?php', '?>', '<?PHP', '<?'), array('','', '' ,'') , $file);
1457                                                                 }
1458                                                 }
1459                                         }
1460                                         $extension .= "\n?>";
1461                                         if($shouldSave){
1462                                                 if(!file_exists("custom/$extpath")){
1463                                                         mkdir_recursive("custom/$extpath", true);
1464                                                 }
1465                                                 $out = sugar_fopen("custom/$extpath/$name", 'w');
1466                                                 fwrite($out,$extension);
1467                                                 fclose($out);
1468                                         }else{
1469                                         if(file_exists("custom/$extpath/$name")){
1470                                                 unlink("custom/$extpath/$name");
1471                                         }
1472                                 }
1473
1474 }
1475
1476     /*
1477      * ModuleInstaller->install_beans runs through the list of beans given, instantiates each bean, calls bean->create_tables, and then calls SugarBean::createRelationshipMeta for the
1478      * bean/module.
1479      */
1480         function install_beans($beans){
1481         include('include/modules.php');
1482                 foreach($beans as $bean){
1483                         $this->log( translate('LBL_MI_IN_BEAN') . " $bean");
1484                         if(isset($beanList[$bean])){
1485                                 $class = $beanList[$bean];
1486                                 if(file_exists($beanFiles[$class])){
1487                                         require_once($beanFiles[$class]);
1488                                         $mod = new $class();
1489                                         //#30273
1490                                         if(is_subclass_of($mod, 'SugarBean')  && $mod->disable_vardefs == false ){
1491                                                 $GLOBALS['log']->debug( "Creating Tables Bean : $bean");
1492                                                 $mod->create_tables();
1493                                                 SugarBean::createRelationshipMeta($mod->getObjectName(), $mod->db,$mod->table_name,'',$mod->module_dir);
1494                                         }
1495                                 }else{
1496                                         $GLOBALS['log']->debug( "File Does Not Exist:" . $beanFiles[$class] );
1497                                 }
1498                         }
1499                 }
1500         }
1501
1502                 function uninstall_beans($beans){
1503                 include('include/modules.php');
1504         foreach($beans as $bean){
1505                         $this->log( translate('LBL_MI_UN_BEAN') . " $bean");
1506                         if(isset($beanList[$bean])){
1507                                 $class = $beanList[$bean];
1508
1509                                 if(file_exists($beanFiles[$class])){
1510                                         require_once($beanFiles[$class]);
1511                                         $mod = new $class();
1512
1513                                         if(is_subclass_of($mod, 'SugarBean')){
1514                                                 $GLOBALS['log']->debug( "Drop Tables : $bean");
1515                                                 if(isset($GLOBALS['mi_remove_tables']) && $GLOBALS['mi_remove_tables'])
1516                                                         $mod->drop_tables();
1517                                         }
1518                                 }else{
1519                                         $GLOBALS['log']->debug( "File Does Not Exist:" . $beanFiles[$class] );
1520                                 }
1521                         }
1522                 }
1523         }
1524
1525         /**
1526          * Remove any customizations made within Studio while the module was installed.
1527          */
1528         function uninstall_customizations($beans){
1529         foreach($beans as $bean){
1530                         $dirs = array(
1531                                 'custom/modules/' . $bean,
1532                                 'custom/Extension/modules/' . $bean
1533                         );
1534                 foreach($dirs as $dir)
1535                 {
1536                                 if(is_dir($dir)){
1537                                         rmdir_recursive($dir);
1538                                 }
1539                 }
1540                 }
1541         }
1542
1543         function log($str){
1544                 $GLOBALS['log']->debug('ModuleInstaller:'. $str);
1545                 if(!$this->silent){
1546                         echo $str . '<br>';
1547                 }
1548         }
1549
1550 /* BEGIN - RESTORE POINT - by MR. MILK August 31, 2005 02:15:18 PM      */
1551 function copy_recursive_with_backup( $source, $dest, $backup_path, $uninstall=false ) {
1552         if(is_file($source)) {
1553             if($uninstall) {
1554                     $GLOBALS['log']->debug("Restoring ... " . $source.  " to " .$dest );
1555                     if(copy( $source, $dest)) {
1556                             if(is_writable($dest))
1557                                 sugar_touch( $dest, filemtime($source) );
1558                         return(unlink($source));
1559                 }
1560                     else {
1561                         $GLOBALS['log']->debug( "Can't restore file: " . $source );
1562                         return true;
1563                 }
1564             }
1565             else {
1566                         if(file_exists($dest)) {
1567                                 $rest = clean_path($backup_path."/$dest");
1568                                 if( !is_dir(dirname($rest)) )
1569                                         mkdir_recursive(dirname($rest), true);
1570
1571                                 $GLOBALS['log']->debug("Backup ... " . $dest.  " to " .$rest );
1572                                 if(copy( $dest, $rest)) {
1573                                         if(is_writable($rest))
1574                                                 sugar_touch( $rest, filemtime($dest) );
1575                                 }
1576                                 else {
1577                                         $GLOBALS['log']->debug( "Can't backup file: " . $dest );
1578                                 }
1579                         }
1580                         return( copy( $source, $dest ) );
1581                 }
1582     }
1583     elseif(!is_dir($source)) {
1584             if($uninstall) {
1585                         if(is_file($dest))
1586                                 return(unlink($dest));
1587                         else {
1588                                 //don't do anything we already cleaned up the files using uninstall_new_files
1589                                 return true;
1590                         }
1591                 }
1592                 else
1593                         return false;
1594         }
1595
1596     if( !is_dir($dest) && !$uninstall){
1597         sugar_mkdir( $dest );
1598     }
1599
1600     $status = true;
1601
1602     $d = dir( $source );
1603     while( $f = $d->read() ){
1604         if( $f == "." || $f == ".." ){
1605             continue;
1606         }
1607         $status &= $this->copy_recursive_with_backup( "$source/$f", "$dest/$f", $backup_path, $uninstall );
1608     }
1609     $d->close();
1610     return( $status );
1611 }
1612
1613 private function dir_get_files($path, $base_path){
1614         $files = array();
1615         if(!is_dir($path))return $files;
1616         $d = dir($path);
1617         while ($e = $d->read()){
1618                 //ignore invisible files . .. ._MACOSX
1619                 if(substr($e, 0, 1) == '.')continue;
1620                 if(is_file($path . '/' . $e))$files[str_replace($base_path , '', $path . '/' . $e)] = str_replace($base_path , '', $path . '/' . $e);
1621                 if(is_dir($path . '/' . $e))$files = array_merge($files, $this->dir_get_files($path . '/' . $e, $base_path));
1622         }
1623         $d->close();
1624         return $files;
1625
1626 }
1627
1628 private function dir_file_count($path){
1629         //if its a file then it has at least 1 file in the directory
1630         if(is_file($path)) return 1;
1631         if(!is_dir($path)) return 0;
1632         $d = dir($path);
1633         $count = 0;
1634         while ($e = $d->read()){
1635                 //ignore invisible files . .. ._MACOSX
1636                 if(substr($e, 0, 1) == '.')continue;
1637                 if(is_file($path . '/' . $e))$count++;
1638                 if(is_dir($path . '/' . $e))$count += $this->dir_file_count($path . '/' . $e);
1639         }
1640         $d->close();
1641         return $count;
1642
1643
1644 }
1645 /* END - RESTORE POINT - by MR. MILK August 31, 2005 02:15:34 PM */
1646
1647
1648         /**
1649          * Static function which allows a module developer to abort their progress, pass in an array of errors and
1650          * redirect back to the main module loader page
1651          *
1652          * @param errors        an array of error messages which will be displayed on the
1653          *                                      main module loader page once it is loaded.
1654          */
1655         function abort($errors = array()){
1656                 //set the errors onto the session so we can display them one the moduler loader page loads
1657                 $_SESSION['MODULEINSTALLER_ERRORS'] = $errors;
1658                 echo '<META HTTP-EQUIV="Refresh" content="0;url=index.php?module=Administration&action=UpgradeWizard&view=module">';
1659                 die();
1660                 //header('Location: index.php?module=Administration&action=UpgradeWizard&view=module');
1661         }
1662
1663         /**
1664          * Return the set of errors stored in the SESSION
1665          *
1666          * @return an array of errors
1667          */
1668         function getErrors(){
1669                 if(!empty($_SESSION['MODULEINSTALLER_ERRORS'])){
1670                         $errors = $_SESSION['MODULEINSTALLER_ERRORS'];
1671                         unset($_SESSION['MODULEINSTALLER_ERRORS']);
1672                         return $errors;
1673                 }
1674                 else
1675                         return null;
1676         }
1677
1678         /*
1679      * Add any fields to the DetailView and EditView of the appropriate modules
1680      * Only add into deployed modules, as addFieldsToUndeployedLayouts has done this already for undeployed modules (and the admin might have edited the layouts already)
1681      * @param array $layoutAdditions  An array of module => fieldname
1682      * return null
1683      */
1684         function addFieldsToLayout($layoutAdditions) {
1685         require_once 'modules/ModuleBuilder/parsers/views/GridLayoutMetaDataParser.php' ;
1686
1687         // these modules either lack editviews/detailviews or use custom mechanisms for the editview/detailview.
1688         // In either case, we don't want to attempt to add a relate field to them
1689         // would be better if GridLayoutMetaDataParser could handle this gracefully, so we don't have to maintain this list here
1690         $invalidModules = array ( 'emails' , 'kbdocuments' ) ;
1691
1692         foreach ( $layoutAdditions as $deployedModuleName => $fieldName )
1693         {
1694             if ( ! in_array( strtolower ( $deployedModuleName ) , $invalidModules ) )
1695             {
1696                 foreach ( array ( MB_EDITVIEW , MB_DETAILVIEW ) as $view )
1697                 {
1698                     $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": adding $fieldName to $view layout for module $deployedModuleName" ) ;
1699                     $parser = new GridLayoutMetaDataParser ( $view, $deployedModuleName ) ;
1700                     $parser->addField ( array ( 'name' => $fieldName ) ) ;
1701                     $parser->handleSave ( false ) ;
1702                 }
1703             }
1704         }
1705
1706         }
1707
1708         function removeFieldsFromLayout($layoutAdditions) {
1709         require_once 'modules/ModuleBuilder/parsers/views/GridLayoutMetaDataParser.php' ;
1710
1711         // these modules either lack editviews/detailviews or use custom mechanisms for the editview/detailview.
1712         // In either case, we don't want to attempt to add a relate field to them
1713         // would be better if GridLayoutMetaDataParser could handle this gracefully, so we don't have to maintain this list here
1714         $invalidModules = array ( 'emails' , 'kbdocuments' ) ;
1715
1716         foreach ( $layoutAdditions as $deployedModuleName => $fieldName )
1717         {
1718             if ( ! in_array( strtolower ( $deployedModuleName ) , $invalidModules ) )
1719             {
1720                 foreach ( array ( MB_EDITVIEW , MB_DETAILVIEW ) as $view )
1721                 {
1722                     $GLOBALS [ 'log' ]->debug ( get_class ( $this ) . ": adding $fieldName to $view layout for module $deployedModuleName" ) ;
1723                     $parser = new GridLayoutMetaDataParser ( $view, $deployedModuleName ) ;
1724                     $parser->removeField ( $fieldName ) ;
1725                     $parser->handleSave ( false ) ;
1726                 }
1727             }
1728         }
1729
1730         }
1731
1732         ///////////////////
1733         //********** DISABLE/ENABLE FUNCTIONS
1734         ///////////////////
1735         function enable($base_dir, $is_upgrade = false, $previous_version = ''){
1736                 global $app_strings;
1737                 $this->base_dir = $base_dir;
1738                 $total_steps = 3; //minimum number of steps with no tasks
1739                 $current_step = 0;
1740                 $tasks = array(
1741                                                                 'enable_copy',
1742                                                                 'enable_menus',
1743                                                                 'enable_userpage',
1744                                                                 'enable_dashlets',
1745                                                                 'enable_administration',
1746                                                                 'enable_vardefs',
1747                                                                 'enable_layoutdefs',
1748                                                                 'enable_relationships',
1749                                                                 'enable_languages',
1750                                                                 'enable_logichooks',
1751                                                                 'reset_opcodes',
1752                 );
1753                 $total_steps += count($tasks);
1754                 if(file_exists($this->base_dir . '/manifest.php')){
1755                                 if(!$this->silent){
1756                                         $current_step++;
1757                                         display_progress_bar('install', $current_step, $total_steps);
1758                                         echo '<div id ="displayLoglink" ><a href="#" onclick="toggleDisplay(\'displayLog\')">'.$app_strings['LBL_DISPLAY_LOG'].'</a> </div><div id="displayLog" style="display:none">';
1759                                 }
1760
1761                                 require_once($this->base_dir . '/manifest.php');
1762                                 if($is_upgrade && !empty($previous_version)){
1763                                         //check if the upgrade path exists
1764                                         if(!empty($upgrade_manifest)){
1765                                                 if(!empty($upgrade_manifest['upgrade_paths'])){
1766                                                         if(!empty($upgrade_manifest['upgrade_paths'][$previous_version])){
1767                                                                 $installdefs =  $upgrade_manifest['upgrade_paths'][$previous_version];
1768                                                         }else{
1769                                                                 $errors[] = 'No Upgrade Path Found in manifest.';
1770                                                                 $this->abort($errors);
1771                                                         }//fi
1772                                                 }//fi
1773                                         }//fi
1774                                 }//fi
1775                                 $this->id_name = $installdefs['id'];
1776                                 $this->installdefs = $installdefs;
1777                                 $installed_modules = array();
1778                                 if(isset($installdefs['beans'])){
1779                                         foreach($this->installdefs['beans'] as $bean){
1780                                                 $installed_modules[] = $bean['module'];
1781                                         }
1782                                         if(!file_exists("custom/Extension/application/Ext/Include")){
1783                                                 mkdir_recursive("custom/Extension/application/Ext/Include", true);
1784                                         }
1785                                         if (file_exists("custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php'))
1786                                                 rename("custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php',"custom/Extension/application/Ext/Include/$this->id_name.php");
1787                                         $this->rebuild_modules();
1788                                 }
1789                                 if(!$this->silent){
1790                                         $current_step++;
1791                                         update_progress_bar('install', $current_step, $total_steps);
1792                                 }
1793
1794                                 foreach($tasks as $task){
1795                                         $this->$task();
1796                                         if(!$this->silent){
1797                                                 $current_step++;
1798                                                 update_progress_bar('install', $current_step, $total_steps);
1799                                         }
1800                                 }
1801
1802                                 if(!$this->silent){
1803                                         $current_step++;
1804                                         update_progress_bar('install', $current_step, $total_steps);
1805                                         echo '</div>';
1806                                 }
1807                                 UpdateSystemTabs('Add',$installed_modules);
1808                                 $GLOBALS['log']->debug('Complete');
1809
1810                 }else{
1811                         die("No \$installdefs Defined In $this->base_dir/manifest.php");
1812                 }
1813
1814         }
1815         function disable($base_dir){
1816                 global $app_strings;
1817                 $total_steps = 3; //min steps with no tasks
1818                 $current_step = 0;
1819                 $this->base_dir = $base_dir;
1820                 $tasks = array(
1821                                                         'disable_copy',
1822                                                         'disable_menus',
1823                                                         'disable_dashlets',
1824                                                         'disable_userpage',
1825                                                         'disable_administration',
1826                                                         'disable_vardefs',
1827                                                         'disable_layoutdefs',
1828                                                         'disable_relationships',
1829                                                         'disable_languages',
1830                                                         'disable_logichooks',
1831                                                         'reset_opcodes',
1832                                                         );
1833                 $total_steps += count($tasks); //now the real number of steps
1834                 if(file_exists($this->base_dir . '/manifest.php')){
1835                                 if(!$this->silent){
1836                                         $current_step++;
1837                                         display_progress_bar('install', $current_step, $total_steps);
1838                                         echo '<div id ="displayLoglink" ><a href="#" onclick="toggleDisplay(\'displayLog\')">'.$app_strings['LBL_DISPLAY_LOG'].'</a> </div><div id="displayLog" style="display:none">';
1839                                 }
1840
1841                                 require_once($this->base_dir . '/manifest.php');
1842                                 $this->installdefs = $installdefs;
1843                                 $this->id_name = $this->installdefs['id'];
1844                                 $installed_modules = array();
1845                                 if(isset($this->installdefs['beans'])){
1846                                         foreach($this->installdefs['beans'] as $bean){
1847                                                 $installed_modules[] = $bean['module'];
1848                                         }
1849
1850                                         mkdir_recursive("custom/Extension/application/Ext/Include/".DISABLED_PATH, true);
1851
1852                                         //Clear any older disabled version
1853                                         if (file_exists("custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php'))
1854                                                 rmdir_recursive("custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php');
1855
1856                                         if (file_exists("custom/Extension/application/Ext/Include/$this->id_name.php"))
1857                                                 rename("custom/Extension/application/Ext/Include/$this->id_name.php", "custom/Extension/application/Ext/Include/".DISABLED_PATH.'/'. $this->id_name . '.php');
1858                                         $this->rebuild_modules();
1859                                 }
1860                                 if(!$this->silent){
1861                                         $current_step++;
1862                                         update_progress_bar('install', $current_step, $total_steps);
1863                                 }
1864                                 foreach($tasks as $task){
1865                                         $this->$task();
1866                                         if(!$this->silent){
1867                                                 $current_step++;
1868                                                 update_progress_bar('install', $current_step, $total_steps);
1869                                         }
1870                                 }
1871                                 if(!$this->silent){
1872                                         $current_step++;
1873                                         update_progress_bar('install', $current_step, $total_steps);
1874                                         echo '</div>';
1875                                 }
1876                         UpdateSystemTabs('Restore',$installed_modules);
1877
1878                 }else{
1879                         die("No manifest.php Defined In $this->base_dir/manifest.php");
1880                 }
1881         }
1882         function enable_vardef($to_module){
1883                 if(isset($this->installdefs['vardefs'])){
1884                         foreach($this->installdefs['vardefs'] as $vardefs){
1885                         $GLOBALS['log']->debug("Enabling Vardefs ..." .$to_module);
1886                         $path = 'custom/Extension/modules/' . $to_module. '/Ext/Vardefs';
1887                         if($to_module == 'application'){
1888                                 $path ='custom/Extension/' . $to_module. '/Ext/Vardefs';
1889                         }
1890                         if(!file_exists($path)){
1891                                 mkdir_recursive($path, true);
1892                         }
1893                         if (file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php'))
1894                                 rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php',  $path . '/'. $this->id_name . '.php');
1895                         if (file_exists($path . '/'.DISABLED_PATH.'/'. basename($vardefs['from'])))
1896                                 rename($path . '/'.DISABLED_PATH.'/'. basename($vardefs['from']),  $path . '/'. basename($vardefs['from']));
1897                         }
1898                 }
1899         }
1900         function enable_vardefs(){
1901                 if(isset($this->installdefs['vardefs'])){
1902                         foreach($this->installdefs['vardefs'] as $vardefs){
1903                                 $vardefs['from'] = str_replace('<basepath>', $this->base_dir, $vardefs['from']);
1904                                 $GLOBALS['log']->debug("Enabling Vardefs ..." . $vardefs['from'] .  " for " .$vardefs['to_module']);
1905                                 $path = 'custom/Extension/modules/' . $vardefs['to_module']. '/Ext/Vardefs';
1906                                 if($vardefs['to_module'] == 'application'){
1907                                         $path ='custom/Extension/' . $vardefs['to_module']. '/Ext/Vardefs';
1908                                 }
1909                                 if(file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php'))
1910                                         rename( $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php', $path . '/'. $this->id_name . '.php');
1911
1912                                 if (file_exists($path . '/'.DISABLED_PATH.'/'. basename($vardefs['from'])))
1913                                         rename($path . '/'.DISABLED_PATH.'/'. basename($vardefs['from']),  $path . '/'. basename($vardefs['from']));
1914
1915                         }
1916                         $this->rebuild_vardefs();
1917                 }
1918         }
1919         function disable_vardefs(){
1920                 $GLOBALS['log']->debug("Disabling Vardefs ".var_export($this->installdefs, true));
1921                 if(isset($this->installdefs['vardefs'])){
1922                         foreach($this->installdefs['vardefs'] as $vardefs){
1923                                 $vardefs['from'] = str_replace('<basepath>', $this->base_dir, $vardefs['from']);
1924                                 $GLOBALS['log']->debug("Disabling Vardefs ..." . $vardefs['from'] .  " for " .$vardefs['to_module']);
1925                                 $path = 'custom/Extension/modules/' . $vardefs['to_module']. '/Ext/Vardefs';
1926                                 if($vardefs['to_module'] == 'application'){
1927                                         $path ='custom/Extension/' . $vardefs['to_module']. '/Ext/Vardefs';
1928                                 }
1929                                 if(file_exists($path . '/'. $this->id_name . '.php')) {
1930                                         mkdir_recursive($path . '/'.DISABLED_PATH, true);
1931                                         rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
1932                                 }
1933                                 if(file_exists($path . '/'. basename($vardefs['from'])))
1934                                 {
1935                                         mkdir_recursive($path . '/'.DISABLED_PATH, true);
1936                                         rename( $path . '/'. basename($vardefs['from']), $path . '/'.DISABLED_PATH.'/'.basename($vardefs['from']));
1937                                 }
1938                         }
1939                         $this->rebuild_vardefs();
1940                 }
1941         }
1942
1943         function enable_relationships(){
1944                 if(isset($this->installdefs['relationships'])){
1945                         $str = "<?php \n //WARNING: The contents of this file are auto-generated\n";
1946                         $save_table_dictionary = false;
1947                         foreach($this->installdefs['relationships'] as $relationship){
1948                 $filename       =basename($relationship['meta_data']);
1949
1950                                 $save_table_dictionary  = true;
1951                                 $str .= "include_once('metadata/$filename');\n";
1952                                 if (empty($relationship['module']))
1953                                     continue;
1954
1955                                 if(!empty($relationship['module_vardefs'])){
1956                                         $this->enable_vardef($relationship['module']);
1957                                 }
1958                                 if(!empty($relationship['module_layoutdefs'])){
1959                                         $this->enable_layoutdef($relationship['module']);
1960                                 }
1961                         }
1962                         $this->rebuild_vardefs();
1963                         $this->rebuild_layoutdefs();
1964                         if($save_table_dictionary){
1965                                 if(!file_exists("custom/Extension/application/Ext/TableDictionary")){
1966                                         mkdir_recursive("custom/Extension/application/Ext/TableDictionary", true);
1967                                 }
1968                                 if (file_exists("custom/Extension/application/Ext/TableDictionary/".DISABLED_PATH."/$this->id_name.php"))
1969                                    rename("custom/Extension/application/Ext/TableDictionary/".DISABLED_PATH."/$this->id_name.php", "custom/Extension/application/Ext/TableDictionary/$this->id_name.php");
1970                                 $this->rebuild_tabledictionary();
1971                         }
1972                 }
1973         }
1974
1975         function disable_relationships($action = 'disable'){
1976                 if(isset($this->installdefs['relationships'])){
1977                         foreach($this->installdefs['relationships'] as $relationship){
1978                                 $filename = basename($relationship['meta_data']);
1979                 $relName = substr($filename, -12) == "MetaData.php" ? substr($filename,0,strlen($filename) - 12) : "";
1980                                 if (empty($relationship['module']) && empty($relName))
1981                         continue;
1982
1983                                 //remove the vardefs
1984                                 if (empty($relName))
1985                                         $path = 'custom/Extension/modules/' . $relationship['module']. '/Ext/Vardefs';
1986                                 if(!empty($relationship['module']) && $relationship['module'] == 'application'){
1987                                         $path ='custom/Extension/' . $relationship['module']. '/Ext/Vardefs';
1988                                 }
1989                                 if(!empty($relationship['module_vardefs']) && file_exists($path . '/'. $this->id_name . '.php')){
1990                                         mkdir_recursive($path . '/'.DISABLED_PATH, true);
1991                                         rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
1992                                 }
1993                                 //remove the layoutdefs
1994                                 if ( !empty($relationship['module']) ) {
1995                     $path = 'custom/Extension/modules/' . $relationship['module']. '/Ext/Layoutdefs';
1996                     if($relationship['module'] == 'application'){
1997                         $path ='custom/Extension/' . $relationship['module']. '/Ext/Layoutdefs';
1998                     }
1999                                 }
2000
2001                                 if(!empty($relationship['module_layoutdefs']) && file_exists($path . '/'. $this->id_name . '.php')){
2002                                         mkdir_recursive($path . '/'.DISABLED_PATH, true);
2003                                         rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
2004                                 }
2005
2006                         }
2007                         if(file_exists("custom/Extension/application/Ext/TableDictionary/$this->id_name.php")){
2008                                 mkdir_recursive("custom/Extension/application/Ext/TableDictionary/".DISABLED_PATH, true);
2009                                 rename("custom/Extension/application/Ext/TableDictionary/$this->id_name.php", "custom/Extension/application/Ext/TableDictionary/".DISABLED_PATH."/$this->id_name.php");
2010                         }
2011                         $this->rebuild_tabledictionary();
2012                         $this->rebuild_vardefs();
2013                         $this->rebuild_layoutdefs();
2014                 }
2015         }
2016
2017         function enable_layoutdefs(){
2018                 if(isset($this->installdefs['layoutdefs'])){
2019                         foreach($this->installdefs['layoutdefs'] as $layoutdefs){
2020                                 $this->enable_layoutdef($layoutdefs['to_module'], $this->id_name);
2021                         }
2022                         $this->rebuild_layoutdefs();
2023                 }
2024         }
2025         function enable_layoutdef($to_module){
2026                 $GLOBALS['log']->debug("Enabling Layout Defs ..." .$to_module);
2027                 if(isset($this->installdefs['layoutdefs'])){
2028                         foreach($this->installdefs['layoutdefs'] as $layoutdefs){
2029                                 $path = 'custom/Extension/modules/' . $to_module. '/Ext/Layoutdefs';
2030                                 if($to_module == 'application'){
2031                                         $path ='custom/Extension/' . $to_module. '/Ext/Layoutdefs';
2032                                 }
2033                                 if (file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php'))
2034                                 {
2035                                         rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php',  $path . '/'. $this->id_name . '.php');
2036                                 }
2037                                 if (file_exists($path . '/'.DISABLED_PATH.'/'. basename($layoutdefs['from'])))
2038                                 {
2039                                         rename($path . '/'.DISABLED_PATH.'/'. basename($layoutdefs['from']),  $path . '/'. basename($layoutdefs['from']));
2040                                 }
2041                         }
2042                 }
2043         }
2044
2045         function disable_layoutdefs(){
2046                 if(isset($this->installdefs['layoutdefs'])){
2047                         foreach($this->installdefs['layoutdefs'] as $layoutdefs){
2048                                 $layoutdefs['from'] = str_replace('<basepath>', $this->base_dir, $layoutdefs['from']);
2049                                 $GLOBALS['log']->debug("Disabling Layoutdefs ..." . $layoutdefs['from'] .  " for " .$layoutdefs['to_module']);
2050                                 $path = 'custom/Extension/modules/' . $layoutdefs['to_module']. '/Ext/Layoutdefs';
2051                                 if($layoutdefs['to_module'] == 'application'){
2052                                         $path ='custom/Extension/' . $layoutdefs['to_module']. '/Ext/Layoutdefs';
2053                                 }
2054                                 if (file_exists($path . '/'. $this->id_name . '.php'))
2055                                 {
2056                                         mkdir_recursive($path . '/'.DISABLED_PATH, true);
2057                                         rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
2058                                 }else if (file_exists($path . '/'. basename($layoutdefs['from'])))
2059                                 {
2060                                         mkdir_recursive($path . '/'.DISABLED_PATH, true);
2061                                         rename( $path . '/'. basename($layoutdefs['from']), $path . '/'.DISABLED_PATH.'/'. basename($layoutdefs['from']));
2062                                 }
2063                         }
2064                         $this->rebuild_layoutdefs();
2065                 }
2066         }
2067
2068         function enable_menus(){
2069                 if(isset($this->installdefs['menu'])){
2070                         foreach($this->installdefs['menu'] as $menu){
2071                                 $menu['from'] = str_replace('<basepath>', $this->base_dir, $menu['from']);
2072                                 $GLOBALS['log']->debug("Enabling Menu ..." . $menu['from'].  " for " .$menu['to_module'] );
2073                                 $path = 'custom/Extension/modules/' . $menu['to_module']. '/Ext/Menus';
2074                                 if($menu['to_module'] == 'application'){
2075                                         $path ='custom/Extension/' . $menu['to_module']. '/Ext/Menus';
2076                                 }
2077
2078                                 if(file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php')){
2079                                         rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php',  $path . '/'. $this->id_name . '.php');
2080                                 }
2081
2082                         }
2083                         $this->rebuild_menus();
2084                 }
2085
2086         }
2087
2088         function disable_menus(){
2089                 if(isset($this->installdefs['menu'])){
2090                         foreach($this->installdefs['menu'] as $menu){
2091                                 $menu['from'] = str_replace('<basepath>', $this->base_dir, $menu['from']);
2092                                 $GLOBALS['log']->debug("Disabling Menu ..." . $menu['from'].  " for " .$menu['to_module'] );
2093                                 $path = 'custom/Extension/modules/' . $menu['to_module']. '/Ext/Menus';
2094                                 if($menu['to_module'] == 'application'){
2095                                         $path ='custom/Extension/' . $menu['to_module']. '/Ext/Menus';
2096                                 }
2097                                 if (file_exists( $path . '/'. $this->id_name . '.php'))
2098                                 {
2099                                         mkdir_recursive($path . '/'.DISABLED_PATH, true);
2100                                         rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
2101                                 }
2102                         }
2103                         $this->rebuild_menus();
2104                 }
2105         }
2106
2107         function enable_administration(){
2108                 if(isset($this->installdefs['administration'])){
2109                         foreach($this->installdefs['administration'] as $administration){
2110                                 $administration['from'] = str_replace('<basepath>', $this->base_dir, $administration['from']);
2111                                 $GLOBALS['log']->debug("Installing Administration Section ..." . $administration['from'] );
2112                                 $path = 'custom/Extension/modules/Administration/Ext/Administration';
2113
2114                                 if(file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php')){
2115                                         rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php',  $path . '/'. $this->id_name . '.php');
2116                                 }
2117                         }
2118                         $this->rebuild_administration();
2119                 }
2120
2121         }
2122         function disable_administration(){
2123                 if(isset($this->installdefs['administration'])){
2124                         foreach($this->installdefs['administration'] as $administration){
2125                                 $administration['from'] = str_replace('<basepath>', $this->base_dir, $administration['from']);
2126                                 $GLOBALS['log']->debug("Uninstalling Administration Section ..." . $administration['from'] );
2127                                 $path = 'custom/Extension/modules/Administration/Ext/Administration';
2128                                 if (file_exists($path . '/'. $this->id_name . '.php'))
2129                                 {
2130                                         mkdir_recursive($path . '/'.DISABLED_PATH, true);
2131                                         rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
2132                                 }
2133                         }
2134                         $this->rebuild_administration();
2135                 }
2136         }
2137
2138         function enable_dashlets(){
2139                 if(isset($this->installdefs['dashlets'])){
2140                         foreach($this->installdefs['dashlets'] as $cp){
2141                                 $cp['from'] = str_replace('<basepath>', $this->base_dir, $cp['from']);
2142                                 $path = 'custom/modules/Home/Dashlets/' . $cp['name'] . '/';
2143                                 $disabled_path = 'custom/modules/Home/'.DISABLED_PATH.'Dashlets/' . $cp['name'];
2144                                 $GLOBALS['log']->debug("Enabling Dashlet " . $cp['name'] . "..." . $cp['from'] );
2145                                 if (file_exists($disabled_path))
2146                                 {
2147                                         rename($disabled_path,  $path);
2148                                 }
2149                         }
2150                         include('modules/Administration/RebuildDashlets.php');
2151
2152                 }
2153         }
2154
2155         function disable_dashlets(){
2156                 if(isset($this->installdefs['dashlets'])){
2157                                         foreach($this->installdefs['dashlets'] as $cp){
2158                                                 $path = 'custom/modules/Home/Dashlets/' . $cp['name'];
2159                                                 $disabled_path = 'custom/modules/Home/'.DISABLED_PATH.'Dashlets/' . $cp['name'];
2160                                                 $GLOBALS['log']->debug('Disabling ' .$path);
2161                                                 if (file_exists($path))
2162                                                 {
2163                                                         mkdir_recursive('custom/modules/Home/'.DISABLED_PATH.'Dashlets/', true);
2164                                                         rename( $path, $disabled_path);
2165                                                 }
2166                                         }
2167                                         include('modules/Administration/RebuildDashlets.php');
2168                                 }
2169         }
2170
2171         function enable_languages(){
2172                 $languages = array();
2173                 if(isset($this->installdefs['language'])){
2174                         foreach($this->installdefs['language'] as $packs){
2175                                 $languages[$packs['language']] = $packs['language'];
2176                                 $packs['from'] = str_replace('<basepath>', $this->base_dir, $packs['from']);
2177                                 $GLOBALS['log']->debug("Installing Language Pack ..." . $packs['from']  .  " for " .$packs['to_module']);
2178                                 $path = 'custom/Extension/modules/' . $packs['to_module']. '/Ext/Language';
2179                                 if($packs['to_module'] == 'application'){
2180                                         $path ='custom/Extension/' . $packs['to_module']. '/Ext/Language';
2181                                 }
2182
2183                                 if(!file_exists($path)){
2184                                         mkdir_recursive($path, true);
2185                                 }
2186                                 if (file_exists($path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php'))
2187                                   rename($path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php',  $path.'/'.$packs['language'].'.'. $this->id_name . '.php');
2188                         }
2189                         $this->rebuild_languages($languages);
2190                 }
2191         }
2192
2193         function disable_languages(){
2194                 $languages = array();
2195                 if(isset($this->installdefs['language'])){
2196                         foreach($this->installdefs['language'] as $packs){
2197                                 $languages[$packs['language']] = $packs['language'];
2198                                 $packs['from'] = str_replace('<basepath>', $this->base_dir, $packs['from']);
2199                                 $GLOBALS['log']->debug("Uninstalling Language Pack ..." . $packs['from']  .  " for " .$packs['to_module']);
2200                                 $path = 'custom/Extension/modules/' . $packs['to_module']. '/Ext/Language';
2201                                 if($packs['to_module'] == 'application'){
2202                                         $path ='custom/Extension/' . $packs['to_module']. '/Ext/Language';
2203                                 }
2204                                 mkdir_recursive($path . '/'.DISABLED_PATH, true);
2205                                 if (file_exists($path.'/'.$packs['language'].'.'. $this->id_name . '.php'))
2206                                   rename($path.'/'.$packs['language'].'.'. $this->id_name . '.php', $path.'/'.DISABLED_PATH.'/'.$packs['language'].'.'. $this->id_name . '.php');
2207
2208                         }
2209                         $this->rebuild_languages($languages);
2210                 }
2211         }
2212
2213         function enable_userpage(){
2214                 if(isset($this->installdefs['user_page'])){
2215                                         foreach($this->installdefs['user_page'] as $userpage){
2216                                                 $userpage['from'] = str_replace('<basepath>', $this->base_dir, $userpage['from']);
2217                                                 $GLOBALS['log']->debug("Installing User Page Section ..." . $userpage['from'] );
2218                                                 $path = 'custom/Extension/modules/Users/Ext/UserPage';
2219                                                 if(file_exists($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php')){
2220                                                         rename($path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php',  $path . '/'. $this->id_name . '.php');
2221                                                 }
2222
2223                                         }
2224                                         $this->rebuild_userpage();
2225                                 }
2226
2227         }
2228         function disable_userpage(){
2229                         if(isset($this->installdefs['user_page'])){
2230                                         foreach($this->installdefs['user_page'] as $userpage){
2231                                                 $userpage['from'] = str_replace('<basepath>', $this->base_dir, $userpage['from']);
2232                                                 $GLOBALS['log']->debug("Uninstalling User Page Section ..." . $userpage['from'] );
2233                                                 $path = 'custom/Extension/modules/Users/Ext/UserPage';
2234                                                 if (file_exists( $path . '/'. $this->id_name . '.php')) {
2235                                                         mkdir_recursive($path . '/'.DISABLED_PATH, true);
2236                                                         rename( $path . '/'. $this->id_name . '.php', $path . '/'.DISABLED_PATH.'/'. $this->id_name . '.php');
2237                                                 }
2238                                         }
2239                                         $this->rebuild_userpage();
2240                                 }
2241         }
2242
2243         function enable_copy(){
2244                 //copy files back onto file system. first perform md5 check to determine if anything has been modified
2245                 //here we should just go through the files in the -restore directory and copy those back
2246                 if(isset($GLOBALS['mi_overwrite_files']) && $GLOBALS['mi_overwrite_files']){
2247                         if(!empty($this->installdefs['copy'])){
2248                                 foreach($this->installdefs['copy'] as $cp){
2249                                         $cp['to'] = clean_path(str_replace('<basepath>', $this->base_dir, $cp['to']));
2250                                         $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore/".$cp['to'] );
2251
2252                                         //check if this file exists in the -restore directory
2253                                         if(file_exists($backup_path)){
2254                                                 //since the file exists, then we want do an md5 of the install version and the file system version
2255                                                 //if(is_file($backup_path) && md5_file($backup_path) == md5_file($cp['to'])){
2256                                                         //since the files are the same then we can safely move back from the -restore
2257                                                         //directory into the file system
2258                                                         $GLOBALS['log']->debug("ENABLE COPY:: FROM: ".$cp['from']. " TO: ".$cp['to']);
2259                                                         $this->copy_path($cp['from'], $cp['to']);
2260                                                 /*}else{
2261                                                         //since they are not equal then we need to prompt the user
2262                                                 }*/
2263                                         }//fi
2264                                 }//rof
2265                         }//fi
2266                 }//fi
2267         }
2268
2269         function disable_copy(){
2270                 //when we disable we want to copy the -restore files back into the file system
2271                 //but we should check the version in the module install against the version on the file system
2272                 //if they match then we can copy the file back, but otherwise we should ask the user.
2273
2274 //              $GLOBALS['log']->debug('ModuleInstaller.php->disable_copy()');
2275                 if(isset($GLOBALS['mi_overwrite_files']) && $GLOBALS['mi_overwrite_files']){
2276 //              $GLOBALS['log']->debug('ModuleInstaller.php->disable_copy():mi_overwrite_files=true');
2277                         if(!empty($this->installdefs['copy'])){
2278 //                              $GLOBALS['log']->debug('ModuleInstaller.php->disable_copy(): installdefs not empty');
2279                                 foreach($this->installdefs['copy'] as $cp){
2280                                         $cp['to'] = clean_path(str_replace('<basepath>', $this->base_dir, $cp['to']));
2281                                         $backup_path = clean_path( remove_file_extension(urldecode(hashToFile($_REQUEST['install_file'])))."-restore/".$cp['to'] ); // bug 16966 tyoung - replaced missing assignment to $backup_path
2282                                         //check if this file exists in the -restore directory
2283 //                                      $GLOBALS['log']->debug("ModuleInstaller.php->disable_copy(): backup_path=".$backup_path);
2284                                         if(file_exists($backup_path)){
2285                                                 //since the file exists, then we want do an md5 of the install version and the file system version
2286                                                 $from = str_replace('<basepath>', $this->base_dir, $cp['from']);
2287
2288                                                 //if(is_file($from) && md5_file($from) == md5_file($cp['to'])){
2289                                                         //since the files are the same then we can safely move back from the -restore
2290                                                         //directory into the file system
2291                                                         $GLOBALS['log']->debug("DISABLE COPY:: FROM: ".$backup_path. " TO: ".$cp['to']);
2292                                                         $this->copy_path($backup_path, $cp['to']);
2293                                                 /*}else{
2294                                                         //since they are not equal then we need to prompt the user
2295                                                 }*/
2296                                         }//fi
2297                                 }//rof
2298                         }//fi
2299                 }//fi
2300         }
2301
2302         public function reset_opcodes()
2303     {
2304         /* Bug 39354 - added function_exists check. Not optimal fix, but safe nonetheless.
2305          * This is for the upgrade to 6.1 from pre 6.1, since the utils files haven't been updated to 6.1 when this is called,
2306          * but this file has been updated to 6.1
2307          */
2308         if(function_exists('sugar_clean_opcodes')){
2309             sugar_clean_opcodes();
2310         }
2311     }
2312
2313 }
2314
2315     function UpdateSystemTabs($action, $installed_modules){
2316         require_once("modules/MySettings/TabController.php");
2317         $controller = new TabController();
2318         $isSystemTabsInDB = $controller->is_system_tabs_in_db();
2319         if ($isSystemTabsInDB && !empty($installed_modules))
2320         {
2321             global $moduleList;
2322             switch ($action)
2323             {
2324                 case 'Restore' :
2325                     $currentTabs = $controller->get_system_tabs();
2326                     foreach ($installed_modules as $module)
2327                     {
2328                         if(in_array($module, $currentTabs)){
2329                             unset($currentTabs[$module]);
2330                         }
2331                     }
2332                     $controller->set_system_tabs($currentTabs);;
2333                     break;
2334                 case 'Add' :
2335                     $currentTabs = $controller->get_system_tabs();
2336                     foreach ($installed_modules as $module)
2337                     {
2338                         if(!in_array($module, $currentTabs)){
2339                             $currentTabs[$module] = $module;
2340                         }
2341                     }
2342                     $controller->set_system_tabs($currentTabs);
2343                 default:
2344                     break;
2345             }
2346         }
2347
2348 }
2349
2350
2351 ?>